<commit_before>#![allow(non_camel_case_types)]

extern crate rand;
extern crate rayon;
extern crate time;

use rand::{Rng, SeedableRng, XorShiftRng};
use std::env;
use std::str::FromStr;

trait Joiner {
    fn is_parallel() -> bool;
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send,
              R_A: Send, R_B: Send;
}

struct Parallel;
impl Joiner for Parallel {
    #[inline]
    fn is_parallel() -> bool {
        true
    }
    #[inline]
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send,
              R_A: Send, R_B: Send
    {
        rayon::join(oper_a, oper_b)
    }
}

struct Sequential;
impl Joiner for Sequential {
    #[inline]
    fn is_parallel() -> bool {
        false
    }
    #[inline]
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send,
              R_A: Send, R_B: Send
    {
        let a = oper_a();
        let b = oper_b();
        (a, b)
    }
}

fn quick_sort<J:Joiner, T:PartialOrd+Send>(v: &mut [T]) {
    if v.len() <= 1 {
        return;
    }

    if J::is_parallel() && v.len() <= 5*1024 {
        return quick_sort::<Sequential, T>(v);
    }

    let mid = partition(v);
    let (lo, hi) = v.split_at_mut(mid);
    J::join(|| quick_sort::<J,T>(lo),
            || quick_sort::<J,T>(hi));
}

fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
    let pivot = v.len() - 1;
    let mut i = 0;
    for j in 0..pivot {
        if v[j] <= v[pivot] {
            v.swap(i, j);
            i += 1;
        }
    }
    v.swap(i, pivot);
    i
}

fn main() {
    let mut kilo = 24;
    let mut run_par = true;
    let mut run_seq = true;
    let mut reps = 10;

    let mut args = env::args().skip(1);
    while let Some(arg) = args.next() {
        if arg == "--no-par" {
            run_par = false;
        } else if arg == "--no-seq" {
            run_seq = false;
        } else if arg == "--reps" {
            if let Some(reps_arg) = args.next() {
                match usize::from_str(&reps_arg) {
                    Ok(v) => reps = v,
                    Err(_) => {
                        println!("invalid argument `{}`, expected integer", reps_arg);
                    }
                }
            } else {
                println!("missing argument to --reps");
            }
        } else {
            match usize::from_str(&arg) {
                Ok(v) => kilo = v,
                Err(_) => {
                    println!("invalid argument `{}`, expected integer", arg);
                }
            }
        }
    }

    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
    let mut par_time = 0;
    let mut seq_time = 0;

    rayon::initialize(2);

    for _ in 0 .. reps {
        let data: Vec<_> = (0..kilo*1024).map(|_| rng.next_u32()).collect();

        if run_par {
            let mut data = data.clone();
            let par_start = time::precise_time_ns();
            quick_sort::<Parallel, u32>(&mut data);
            par_time += time::precise_time_ns() - par_start;
        }

        if run_seq {
            let mut data = data.clone();
            let seq_start = time::precise_time_ns();
            quick_sort::<Sequential, u32>(&mut data);
            seq_time += time::precise_time_ns() - seq_start;
        }
    }

    println!("Array length    : {}K 32-bit integers", kilo);
    println!("Repetitions     : {}", reps);
    if run_par { println!("Parallel time   : {}", par_time); }
    if run_seq { println!("Sequential time : {}", seq_time); }
    if run_par && run_seq {
        println!("Parallel speedup: {}", (seq_time as f64) / (par_time as f64));
    }
}
<commit_msg>fix wrong parameter to initialize in quicksort demo<commit_after>#![allow(non_camel_case_types)]

extern crate rand;
extern crate rayon;
extern crate time;

use rand::{Rng, SeedableRng, XorShiftRng};
use std::env;
use std::str::FromStr;

trait Joiner {
    fn is_parallel() -> bool;
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send,
              R_A: Send, R_B: Send;
}

struct Parallel;
impl Joiner for Parallel {
    #[inline]
    fn is_parallel() -> bool {
        true
    }
    #[inline]
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send,
              R_A: Send, R_B: Send
    {
        rayon::join(oper_a, oper_b)
    }
}

struct Sequential;
impl Joiner for Sequential {
    #[inline]
    fn is_parallel() -> bool {
        false
    }
    #[inline]
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send,
              R_A: Send, R_B: Send
    {
        let a = oper_a();
        let b = oper_b();
        (a, b)
    }
}

fn quick_sort<J:Joiner, T:PartialOrd+Send>(v: &mut [T]) {
    if v.len() <= 1 {
        return;
    }

    if J::is_parallel() && v.len() <= 5*1024 {
        return quick_sort::<Sequential, T>(v);
    }

    let mid = partition(v);
    let (lo, hi) = v.split_at_mut(mid);
    J::join(|| quick_sort::<J,T>(lo),
            || quick_sort::<J,T>(hi));
}

fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
    let pivot = v.len() - 1;
    let mut i = 0;
    for j in 0..pivot {
        if v[j] <= v[pivot] {
            v.swap(i, j);
            i += 1;
        }
    }
    v.swap(i, pivot);
    i
}

fn main() {
    let mut kilo = 24;
    let mut run_par = true;
    let mut run_seq = true;
    let mut reps = 10;

    let mut args = env::args().skip(1);
    while let Some(arg) = args.next() {
        if arg == "--no-par" {
            run_par = false;
        } else if arg == "--no-seq" {
            run_seq = false;
        } else if arg == "--reps" {
            if let Some(reps_arg) = args.next() {
                match usize::from_str(&reps_arg) {
                    Ok(v) => reps = v,
                    Err(_) => {
                        println!("invalid argument `{}`, expected integer", reps_arg);
                    }
                }
            } else {
                println!("missing argument to --reps");
            }
        } else {
            match usize::from_str(&arg) {
                Ok(v) => kilo = v,
                Err(_) => {
                    println!("invalid argument `{}`, expected integer", arg);
                }
            }
        }
    }

    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
    let mut par_time = 0;
    let mut seq_time = 0;

    rayon::initialize(None);

    for _ in 0 .. reps {
        let data: Vec<_> = (0..kilo*1024).map(|_| rng.next_u32()).collect();

        if run_par {
            let mut data = data.clone();
            let par_start = time::precise_time_ns();
            quick_sort::<Parallel, u32>(&mut data);
            par_time += time::precise_time_ns() - par_start;
        }

        if run_seq {
            let mut data = data.clone();
            let seq_start = time::precise_time_ns();
            quick_sort::<Sequential, u32>(&mut data);
            seq_time += time::precise_time_ns() - seq_start;
        }
    }

    println!("Array length    : {}K 32-bit integers", kilo);
    println!("Repetitions     : {}", reps);
    if run_par { println!("Parallel time   : {}", par_time); }
    if run_seq { println!("Sequential time : {}", seq_time); }
    if run_par && run_seq {
        println!("Parallel speedup: {}", (seq_time as f64) / (par_time as f64));
    }
}
<|endoftext|>


<commit_before>use escape::escape_html;
use token::Token;
use book::{Book, Number};
use error::{Error,Result};
use templates::odt;
use zipper::Zipper;

use mustache;

/// Rendererer for ODT
/// (Experimental)
pub struct OdtRenderer<'a> {
    book: &'a Book,
    current_numbering: bool,
    current_hide: bool,
    current_chapter: i32,
    automatic_styles: String,
}

impl<'a> OdtRenderer<'a> {
    /// Create a new OdtRenderer
    pub fn new(book: &'a Book) -> OdtRenderer {
        OdtRenderer {
            book: book,
            current_chapter: 1,
            current_numbering: book.numbering,
            current_hide: false,
            automatic_styles: String::from("
<style:style style:name=\"T1\" style:family=\"text\">
  <style:text-properties fo:font-style=\"italic\" style:font-style-asian=\"italic\" style:font-style-complex=\"italic\"/>
</style:style>
<style:style style:name=\"T2\" style:family=\"text\">
  <style:text-properties fo:font-weight=\"bold\" style:font-weight-asian=\"bold\" style:font-weight-complex=\"bold\"/>
</style:style>"),
        }
    }

    /// Render book
    pub fn render_book(&mut self) -> Result<String> {
        let content = try!(self.render_content());

        let mut zipper = try!(Zipper::new(&self.book.temp_dir));

        // Write template.odt there
        try!(zipper.write("template.odt", odt::ODT, false));
        // unzip it
        try!(zipper.unzip("template.odt"));
        // Complete it with content.xml
        try!(zipper.write("content.xml", &content.as_bytes(), false));
        // Zip and copy
        if let Some(ref file) = self.book.output_odt {
            zipper.generate_odt(file)
        } else {
            panic!("odt.render_book called while book.output_odt is not set");
        }
    }

    /// Render content.xml
    pub fn render_content(&mut self) -> Result<String> {
        let mut content = String::new();

        for &(n, ref v) in &self.book.chapters {
            self.current_hide = false;
            match n {
                Number::Unnumbered => self.current_numbering = false,
                Number::Default => self.current_numbering = self.book.numbering,
                Number::Specified(n) => {
                    self.current_numbering = self.book.numbering;
                    self.current_chapter = n;
                },
                Number::Hidden => {
                    self.current_numbering = false;
                    self.current_hide = true;
                },
            }
            for token in v {
                content.push_str(&self.parse_token(token));
            }
        }

        let template = mustache::compile_str(odt::CONTENT);
        let data = self.book.get_mapbuilder("none")
            .insert_str("content", content)
            .insert_str("automatic_styles", &self.automatic_styles)
            .build();

        let mut res:Vec<u8> = vec!();
        template.render_data(&mut res, &data);
        match String::from_utf8(res) {
            Err(_) => Err(Error::Render("generated content.xml was not utf-8 valid")),
            Ok(res) => Ok(res)
        }
    }

    /// Transform a vector of `Token`s to Odt format
    pub fn render_vec(&mut self, tokens:&[Token]) -> String {
        let mut res = String::new();

        for token in tokens {
            res.push_str(&self.parse_token(&token));
        }
        res
    }

    pub fn parse_token(&mut self, token: &Token) -> String {
        match *token {
            Token::Str(ref text) => escape_html(&*text),
            Token::Paragraph(ref vec) => format!("<text:p text:style-name=\"Text_20_body\">{}</text:p>\n", self.render_vec(vec)),
            Token::Header(n, ref vec) => {
                if n == 1 && self.current_hide {
                    return String::new();
                }
                let s = escape_html(&if n == 1 && self.current_numbering {
                    let chapter = self.current_chapter;
                    self.current_chapter += 1;
                    self.book.get_header(chapter, &self.render_vec(vec)).unwrap()
                } else {
                    self.render_vec(vec)
                });
                format!("<text:h text:style-name=\"Heading_20_{}\">\n{}</text:h>\n",
                        n, s)
            },
            Token::Emphasis(ref vec) => format!("<text:span text:style-name=\"T1\">{}</text:span>", self.render_vec(vec)),
            Token::Strong(ref vec) => format!("<text:span text:style-name=\"T2\">{}</text:span>", self.render_vec(vec)),
            Token::List(ref vec) => format!("<text:list>\n{}</text:list>\n", self.render_vec(vec)),
            Token::OrderedList(_, ref vec) => {
                println!("Ordered list not currently implemented for ODT, fallbacking to unordered one");
                format!("<text:list>\n{}</text:list>\n", self.render_vec(vec))
            },
            Token::Item(ref vec) => format!("<text:list-item>\n<text:p>{}</text:p></text:list-item>", self.render_vec(vec)),
            Token::Link(ref url, _, ref vec) => format!("<text:a xlink:type=\"simple\"  xlink:href=\"{}\">{}</text:a>", url, self.render_vec(vec)),
            Token::Code(ref vec) => format!("<text:span text:style-name=\"Preformatted_20_Text\">{}</text:span>", self.render_vec(vec)),
            Token::BlockQuote(ref vec) | Token::CodeBlock(_, ref vec) => {
                println!("warning: block quote and codeblocks are not currently implemented in ODT");
                format!("<text:p text:style-name=\"Text_20_Body\">{}</text:p>\n", self.render_vec(vec))
            },
            Token::SoftBreak | Token::HardBreak => String::from(" "),
            Token::Rule => format!("<text:p /><text:p>***</text:p><text:p />"),
            Token::Image(_,_,_) => {
                println!("warning: images not currently implemented for odt");
                String::from(" ")
            },
        }
    }
}

<commit_msg>fixed issue on stable/beta<commit_after>use escape::escape_html;
use token::Token;
use book::{Book, Number};
use error::{Error,Result};
use templates::odt;
use zipper::Zipper;

use mustache;

/// Rendererer for ODT
/// (Experimental)
pub struct OdtRenderer<'a> {
    book: &'a Book,
    current_numbering: bool,
    current_hide: bool,
    current_chapter: i32,
    automatic_styles: String,
}

impl<'a> OdtRenderer<'a> {
    /// Create a new OdtRenderer
    pub fn new(book: &'a Book) -> OdtRenderer {
        OdtRenderer {
            book: book,
            current_chapter: 1,
            current_numbering: book.numbering,
            current_hide: false,
            automatic_styles: String::from("
<style:style style:name=\"T1\" style:family=\"text\">
  <style:text-properties fo:font-style=\"italic\" style:font-style-asian=\"italic\" style:font-style-complex=\"italic\"/>
</style:style>
<style:style style:name=\"T2\" style:family=\"text\">
  <style:text-properties fo:font-weight=\"bold\" style:font-weight-asian=\"bold\" style:font-weight-complex=\"bold\"/>
</style:style>"),
        }
    }

    /// Render book
    pub fn render_book(&mut self) -> Result<String> {
        let content = try!(self.render_content());

        let mut zipper = try!(Zipper::new(&self.book.temp_dir));

        // Write template.odt there
        try!(zipper.write("template.odt", odt::ODT, false));
        // unzip it
        try!(zipper.unzip("template.odt"));
        // Complete it with content.xml
        try!(zipper.write("content.xml", &content.as_bytes(), false));
        // Zip and copy
        if let Some(ref file) = self.book.output_odt {
            zipper.generate_odt(file)
        } else {
            panic!("odt.render_book called while book.output_odt is not set");
        }
    }

    /// Render content.xml
    pub fn render_content(&mut self) -> Result<String> {
        let mut content = String::new();

        for &(n, ref v) in &self.book.chapters {
            self.current_hide = false;
            match n {
                Number::Unnumbered => self.current_numbering = false,
                Number::Default => self.current_numbering = self.book.numbering,
                Number::Specified(n) => {
                    self.current_numbering = self.book.numbering;
                    self.current_chapter = n;
                },
                Number::Hidden => {
                    self.current_numbering = false;
                    self.current_hide = true;
                },
            }
            for token in v {
                content.push_str(&self.parse_token(token));
            }
        }

        let template = mustache::compile_str(odt::CONTENT);
        let data = self.book.get_mapbuilder("none")
            .insert_str("content", content)
            .insert_str("automatic_styles", &self.automatic_styles)
            .build();

        let mut res:Vec<u8> = vec!();
        template.render_data(&mut res, &data);
        match String::from_utf8(res) {
            Err(_) => Err(Error::Render("generated content.xml was not utf-8 valid")),
            Ok(res) => Ok(res)
        }
    }

    /// Transform a vector of `Token`s to Odt format
    pub fn render_vec(&mut self, tokens:&[Token]) -> String {
        let mut res = String::new();

        for token in tokens {
            res.push_str(&self.parse_token(&token));
        }
        res
    }

    pub fn parse_token(&mut self, token: &Token) -> String {
        match *token {
            Token::Str(ref text) => escape_html(&*text),
            Token::Paragraph(ref vec) => format!("<text:p text:style-name=\"Text_20_body\">{}</text:p>\n", self.render_vec(vec)),
            Token::Header(n, ref vec) => {
                if n == 1 && self.current_hide {
                    return String::new();
                }
                let s = if n == 1 && self.current_numbering {
                    let chapter = self.current_chapter;
                    self.current_chapter += 1;
                    self.book.get_header(chapter, &self.render_vec(vec)).unwrap()
                } else {
                    self.render_vec(vec)
                };
                format!("<text:h text:style-name=\"Heading_20_{}\">\n{}</text:h>\n",
                        n, escape_html(&s))
            },
            Token::Emphasis(ref vec) => format!("<text:span text:style-name=\"T1\">{}</text:span>", self.render_vec(vec)),
            Token::Strong(ref vec) => format!("<text:span text:style-name=\"T2\">{}</text:span>", self.render_vec(vec)),
            Token::List(ref vec) => format!("<text:list>\n{}</text:list>\n", self.render_vec(vec)),
            Token::OrderedList(_, ref vec) => {
                println!("Ordered list not currently implemented for ODT, fallbacking to unordered one");
                format!("<text:list>\n{}</text:list>\n", self.render_vec(vec))
            },
            Token::Item(ref vec) => format!("<text:list-item>\n<text:p>{}</text:p></text:list-item>", self.render_vec(vec)),
            Token::Link(ref url, _, ref vec) => format!("<text:a xlink:type=\"simple\"  xlink:href=\"{}\">{}</text:a>", url, self.render_vec(vec)),
            Token::Code(ref vec) => format!("<text:span text:style-name=\"Preformatted_20_Text\">{}</text:span>", self.render_vec(vec)),
            Token::BlockQuote(ref vec) | Token::CodeBlock(_, ref vec) => {
                println!("warning: block quote and codeblocks are not currently implemented in ODT");
                format!("<text:p text:style-name=\"Text_20_Body\">{}</text:p>\n", self.render_vec(vec))
            },
            Token::SoftBreak | Token::HardBreak => String::from(" "),
            Token::Rule => format!("<text:p /><text:p>***</text:p><text:p />"),
            Token::Image(_,_,_) => {
                println!("warning: images not currently implemented for odt");
                String::from(" ")
            },
        }
    }
}

<|endoftext|>


<commit_before>use std::iter;

/// A structure for manipulating Table Of Content
pub struct Toc {
    elements: Vec<TocElement>,
    numbered: bool,
}

impl Toc {
    /// Create a new, empty, Toc
    pub fn new() -> Toc {
        Toc {
            elements: vec!(),
            numbered: false,
        }
    }

    /// Sets numbering of the Toc
    pub fn numbered(&mut self, numbered: bool) {
        self.numbered = numbered;
    }

    /// Adds an element
    pub fn add(&mut self, level: i32, url: String, title: String) {
        let element = TocElement::new(level, url, title);
        self.elements.push(element);
    }

    /// Render the Toc
    pub fn render(&self) -> String {
        let mut output = String::new();

        let mut x = 0;
        let mut level = 0;
        output.push_str(&self.render_vec(&mut x, &mut level));
        for i in (0..level).rev() {
            output.push_str(&format!("{}</{}>",
                                     iter::repeat(' ').take(i as usize).collect::<String>(),
                                     if self.numbered {"ol"} else {"ul"}));
        }
        output
    }

    fn render_vec(&self, x: &mut usize, level: &mut i32) -> String {
        let orig_level = *level;
        let mut content = String::new();
        while *x < self.elements.len() {
            let elem = &self.elements[*x];

            if elem.level <= orig_level {
                return content
            }

            *x += 1;

            if elem.level > *level {
                for i in *level..elem.level {
                    content.push_str(&format!("{}{}\n",
                                              iter::repeat(' ').take(i as usize).collect::<String>(),
                                              if self.numbered {"
"} else {"
"}));
                    *level = elem.level;
                }
            } else if elem.level < *level {
                for i in (elem.level..*level).rev() {
                    content.push_str(&format!("{}</{}>\n",
                                              iter::repeat(' ').take(i as usize).collect::<String>(),
                                              if self.numbered {"ol"} else {"ul"}));
                }
                *level = elem.level;
            }
            let spaces:String = iter::repeat(' ').take(elem.level as usize).collect();
            content.push_str(&format!("{}
{}\n",
                                      spaces, elem.url, elem.title));
            content.push_str(&self.render_vec(x, level));

            for i in (elem.level..*level).rev() {
                content.push_str(&format!("{}</{}>\n",
                                          iter::repeat(' ').take(i as usize).collect::<String>(),
                                          if self.numbered {"ol"} else {"ul"}));
            }
            *level = elem.level;
            content.push_str(&format!("{}
\n", spaces));

        }
        content
    }
}

struct TocElement {
    level: i32,
    url: String,
    title: String,
}

impl TocElement {
    pub fn new(level: i32, url: String, title: String) -> TocElement {
        TocElement {
            level: level,
            url: url,
            title: title,
        }
    }
}

<commit_msg>toc.rs: minor comment modification<commit_after>use std::iter;

/// A structure for manipulating Table Of Content
pub struct Toc {
    elements: Vec<TocElement>,
    numbered: bool,
}

impl Toc {
    /// Create a new, empty, Toc
    pub fn new() -> Toc {
        Toc {
            elements: vec!(),
            numbered: false,
        }
    }

    /// Sets numbering of the Toc
    pub fn numbered(&mut self, numbered: bool) {
        self.numbered = numbered;
    }

    /// Adds an element
    pub fn add(&mut self, level: i32, url: String, title: String) {
        let element = TocElement::new(level, url, title);
        self.elements.push(element);
    }

    /// Render the Toc in either
 or
 form (according to Self::numbered
    pub fn render(&self) -> String {
        let mut output = String::new();

        let mut x = 0;
        let mut level = 0;
        output.push_str(&self.render_vec(&mut x, &mut level));
        for i in (0..level).rev() {
            output.push_str(&format!("{}</{}>",
                                     iter::repeat(' ').take(i as usize).collect::<String>(),
                                     if self.numbered {"ol"} else {"ul"}));
        }
        output
    }

    fn render_vec(&self, x: &mut usize, level: &mut i32) -> String {
        let orig_level = *level;
        let mut content = String::new();
        while *x < self.elements.len() {
            let elem = &self.elements[*x];

            if elem.level <= orig_level {
                return content
            }

            *x += 1;

            if elem.level > *level {
                for i in *level..elem.level {
                    content.push_str(&format!("{}{}\n",
                                              iter::repeat(' ').take(i as usize).collect::<String>(),
                                              if self.numbered {"
"} else {"
"}));
                    *level = elem.level;
                }
            } else if elem.level < *level {
                for i in (elem.level..*level).rev() {
                    content.push_str(&format!("{}</{}>\n",
                                              iter::repeat(' ').take(i as usize).collect::<String>(),
                                              if self.numbered {"ol"} else {"ul"}));
                }
                *level = elem.level;
            }
            let spaces:String = iter::repeat(' ').take(elem.level as usize).collect();
            content.push_str(&format!("{}
{}\n",
                                      spaces, elem.url, elem.title));
            content.push_str(&self.render_vec(x, level));

            for i in (elem.level..*level).rev() {
                content.push_str(&format!("{}</{}>\n",
                                          iter::repeat(' ').take(i as usize).collect::<String>(),
                                          if self.numbered {"ol"} else {"ul"}));
            }
            *level = elem.level;
            content.push_str(&format!("{}
\n", spaces));

        }
        content
    }
}

struct TocElement {
    level: i32,
    url: String,
    title: String,
}

impl TocElement {
    pub fn new(level: i32, url: String, title: String) -> TocElement {
        TocElement {
            level: level,
            url: url,
            title: title,
        }
    }
}

<|endoftext|>


<commit_before>use nom::alpha;
use std::str;

fn bytes_to_string(bytes: &[u8]) -> String {
    str::from_utf8(bytes).unwrap().to_string()
}

// In Lisp, we can use symbols for identifiers so parse them as such
named!(pub symbol_identifier<String>,
    map!(
        recognize!(
            many0!(
                alt!(tag!("{")
                    | tag!("}")
                    | tag!("(")
                    | tag!(")")
                    | tag!("[")
                    | tag!("]")
                    | tag!(".")
                    | tag!(";")
                    | tag!(",")
                    | tag!("<")
                    | tag!(">")
                    | tag!("=")
                    | tag!("!")
                    | tag!("+")
                    | tag!("-")
                    | tag!("*")
                    | tag!("/")
                    | tag!("&")
                    | tag!("|")
                    | tag!("^")
                    | tag!("~")
                    | tag!("?")
                    | tag!(":")
                )
            )
        ), bytes_to_string
    )
);

// Represents letters etc in identifiers
named!(pub alpha_identifier<String>, map!(recognize!(alpha), bytes_to_string));
<commit_msg>Add an identifier literal parser<commit_after>use nom::alpha;
use std::str;

fn bytes_to_string(bytes: &[u8]) -> String {
    str::from_utf8(bytes).unwrap().to_string()
}

named!(pub identifier_literal<String>,
    alt!(symbol_identifier | alpha_identifier)
);

// In Lisp, we can use symbols for identifiers so parse them as such
named!(pub symbol_identifier<String>,
    map!(
        recognize!(
            many0!(
                alt!(tag!("{")
                    | tag!("}")
                    | tag!("(")
                    | tag!(")")
                    | tag!("[")
                    | tag!("]")
                    | tag!(".")
                    | tag!(";")
                    | tag!(",")
                    | tag!("<")
                    | tag!(">")
                    | tag!("=")
                    | tag!("!")
                    | tag!("+")
                    | tag!("-")
                    | tag!("*")
                    | tag!("/")
                    | tag!("&")
                    | tag!("|")
                    | tag!("^")
                    | tag!("~")
                    | tag!("?")
                    | tag!(":")
                )
            )
        ), bytes_to_string
    )
);

// Represents letters etc in identifiers
named!(pub alpha_identifier<String>,
    map!(
        recognize!(
            tuple!(
                alpha,
                // Somethimes a symbol might follow a letter
                opt!(symbol_identifier)
            )
        ),
        bytes_to_string
    )
);
<|endoftext|>


<commit_before>use std::vec::Vec;
use std::thread;
use std::sync::mpsc;

pub enum Message {
    Pause,
    Resume,
    Step,
    Inspect,
}

pub fn spawn() -> (mpsc::Sender<Message>, mpsc::Receiver<String>) {
    let (tx_message, rx_message) = mpsc::channel();
    let (tx_data, rx_data) = mpsc::channel();

    thread::spawn(move || {
        let mut computer = Machine::new();
        let mut paused = false;

        loop {
            let message = rx_message.try_recv();
            if message.is_ok() {
                match message.unwrap() {
                    Message::Pause => {
                        paused = true;
                    },

                    Message::Resume => {
                        paused = false;
                    },

                    Message::Step => {
                        paused = true;
                        computer.step();
                    },

                    Message::Inspect => {
                        let data = format!("PAUSED {}\nPC {}", paused, computer.loc());
                        tx_data.send(data).unwrap();
                    }
                }
            }

            thread::yield_now();

            if !paused {
                computer.step();
            }

        }
    });

    return (tx_message, rx_data);
}

pub struct Machine {
    memory: Vec<u32>,
    counter: u32,
}

impl Machine {
    pub fn new() -> Machine {
        Machine {
            // Default to a valid program in memory.
            // This one is an infinite loop.
            memory: vec![1, 2, 0, 0],
            counter: 0,
        }
    }

    pub fn loc(&self) -> u32 {
        self.counter
    }

    pub fn dump(&self) -> &Vec<u32> {
        &self.memory
    }

    pub fn step(&mut self) {
        let counter = self.counter;
        let opcode = self.read(counter);
        let a = self.read(counter + 1);
        let b = self.read(counter + 2);
        let c = self.read(counter + 3);
        self.exec(opcode, a, b, c);
    }

    fn read(&mut self, index: u32) -> u32 {
        let index = index as usize;

        if index >= self.memory.len() {
            self.memory.resize(index + 1, 0);
        }

        return self.memory[index];
    }

    fn exec(&mut self, opcode: u32, a: u32, b: u32, c: u32) {
        match opcode {
            // PC <- M[A]
            1 => {
                self.counter = self.memory[a as usize];
            },

            // If M[B] = 0, then PC <- M[A]
            2 => {
                if 0 == self.memory[b as usize] {
                  self.counter = self.memory[a as usize];
                }
            },

            // M[A] <- PC
            3 => {
                self.memory[a as usize] = self.counter;
                self.counter += 4;
            },

            // M[A] <- M[B]
            4 => {
                self.memory[a as usize] = self.memory[b as usize];
                self.counter += 4;
            },

            // M[A] <- M[M[B]]
            5 => {
                let b = self.memory[b as usize];
                self.memory[a as usize] = self.memory[b as usize];
                self.counter += 4;
            },

            // M[M[B]] <- M[A]
            6 => {
                let b = self.memory[b as usize];
                self.memory[b as usize] = self.memory[a as usize];
                self.counter += 4;
            },

            // M[A] <- M[B] + M[C]
            7 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b + c;
                self.counter += 4;
            },

            // M[A] <- M[B] - M[C]
            8 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b - c;
                self.counter += 4;
            },

            // M[A] <- M[B] * M[C]
            9 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b * c;
                self.counter += 4;
            },

            // M[A] <- M[B] / M[C]
            10 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b / c;
                self.counter += 4;
            },

            // M[A] <- M[B] % M[C]
            11 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b % c;
                self.counter += 4;
            },

            // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
            12 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                if b < c {
                  self.memory[a as usize] = 1;
                } else {
                  self.memory[a as usize] = 0;
                }
                self.counter += 4;
            },

            // MA[A] <- NOT(M[B] AND M[C])
            13 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                if b > 0 && c > 0 {
                  self.memory[a as usize] = 0;
                } else {
                  self.memory[a as usize] = 1;
                }
                self.counter += 4;
            },

            // Unknown opcode
            _ => {
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Machine;

    #[test]
    fn it_defaults_to_an_infinite_loop() {
        let mut m = Machine::new();

        // Read initial memory and program counter.
        let memory = m.dump().to_vec();
        let counter = m.loc();

        // Step the program twice. If nothing changes, we're in a loop.
        m.step();
        assert_eq!(counter, m.loc());
        assert_eq!(&memory, m.dump());
        m.step();
        assert_eq!(counter, m.loc());
        assert_eq!(&memory, m.dump());
    }

    #[test]
    fn it_runs_opcode_1() {
        // PC <- M[A]
        let mut m = Machine { memory: vec![1, 4, 0, 0, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_then_branch() {
        // If M[B] = 0, then PC <- M[A]
        let mut m = Machine { memory: vec![2, 4, 5, 0, 2, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_else_branch() {
        // If M[B] = 0, then PC <- M[A]
        let mut m = Machine { memory: vec![2, 4, 5, 0, 2, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(0, m.loc());
    }

    #[test]
    fn it_runs_opcode_3() {
        // M[A] <- PC
        let mut m = Machine { memory: vec![3, 4, 0, 0, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![3, 4, 0, 0, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_4() {
        // M[A] <- M[B]
        let mut m = Machine { memory: vec![4, 4, 5, 0, 6, 7], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![4, 4, 5, 0, 7, 7], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_5() {
        // M[A] <- M[M[B]]
        let mut m = Machine { memory: vec![5, 4, 5, 0, 6, 7, 0, 8], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![5, 4, 5, 0, 8, 7, 0, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_6() {
        // M[M[B]] <- M[A]
        let mut m = Machine { memory: vec![6, 4, 5, 0, 8, 6, 7], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![6, 4, 5, 0, 8, 6, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_7() {
        // M[A] <- M[B] + M[C]
        let mut m = Machine { memory: vec![7, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![7, 4, 5, 6, 13, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_8() {
        // M[A] <- M[B] - M[C]
        let mut m = Machine { memory: vec![8, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![8, 4, 5, 6, 9, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_9() {
        // M[A] <- M[B] * M[C]
        let mut m = Machine { memory: vec![9, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![9, 4, 5, 6, 22, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_10() {
        // M[A] <- M[B] / M[C]
        let mut m = Machine { memory: vec![10, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![10, 4, 5, 6, 5, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_11() {
        // M[A] <- M[B] % M[C]
        let mut m = Machine { memory: vec![11, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![11, 4, 5, 6, 1, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_12_then_branch() {
        // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
        let mut m = Machine { memory: vec![12, 4, 5, 6, 2, 8, 9], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![12, 4, 5, 6, 1, 8, 9], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_12_else_branch() {
        // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
        let mut m = Machine { memory: vec![12, 4, 5, 6, 2, 9, 8], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![12, 4, 5, 6, 0, 9, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_false_false_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 0, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 0, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_false_true_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 0, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 0, 1], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_true_false_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 1, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 1, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_true_true_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 1, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 0, 1, 1], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_provides_safe_memory_access_when_stepping() {
        let mut m = Machine { memory: vec![0], counter: 3 };

        m.step();
        assert_eq!(&vec![0, 0, 0, 0, 0, 0, 0], m.dump());
    }
}
<commit_msg>Replace memory[] calls with read().<commit_after>use std::vec::Vec;
use std::thread;
use std::sync::mpsc;

pub enum Message {
    Pause,
    Resume,
    Step,
    Inspect,
}

pub fn spawn() -> (mpsc::Sender<Message>, mpsc::Receiver<String>) {
    let (tx_message, rx_message) = mpsc::channel();
    let (tx_data, rx_data) = mpsc::channel();

    thread::spawn(move || {
        let mut computer = Machine::new();
        let mut paused = false;

        loop {
            let message = rx_message.try_recv();
            if message.is_ok() {
                match message.unwrap() {
                    Message::Pause => {
                        paused = true;
                    },

                    Message::Resume => {
                        paused = false;
                    },

                    Message::Step => {
                        paused = true;
                        computer.step();
                    },

                    Message::Inspect => {
                        let data = format!("PAUSED {}\nPC {}", paused, computer.loc());
                        tx_data.send(data).unwrap();
                    }
                }
            }

            thread::yield_now();

            if !paused {
                computer.step();
            }

        }
    });

    return (tx_message, rx_data);
}

pub struct Machine {
    memory: Vec<u32>,
    counter: u32,
}

impl Machine {
    pub fn new() -> Machine {
        Machine {
            // Default to a valid program in memory.
            // This one is an infinite loop.
            memory: vec![1, 2, 0, 0],
            counter: 0,
        }
    }

    pub fn loc(&self) -> u32 {
        self.counter
    }

    pub fn dump(&self) -> &Vec<u32> {
        &self.memory
    }

    pub fn step(&mut self) {
        let counter = self.counter;
        let opcode = self.read(counter);
        let a = self.read(counter + 1);
        let b = self.read(counter + 2);
        let c = self.read(counter + 3);
        self.exec(opcode, a, b, c);
    }

    fn read(&mut self, index: u32) -> u32 {
        let index = index as usize;

        if index >= self.memory.len() {
            self.memory.resize(index + 1, 0);
        }

        return self.memory[index];
    }

    fn exec(&mut self, opcode: u32, a: u32, b: u32, c: u32) {
        match opcode {
            // PC <- M[A]
            1 => {
                self.counter = self.read(a);
            },

            // If M[B] = 0, then PC <- M[A]
            2 => {
                if 0 == self.read(b) {
                  self.counter = self.read(a);
                }
            },

            // M[A] <- PC
            3 => {
                self.memory[a as usize] = self.counter;
                self.counter += 4;
            },

            // M[A] <- M[B]
            4 => {
                self.memory[a as usize] = self.read(b);
                self.counter += 4;
            },

            // M[A] <- M[M[B]]
            5 => {
                let b = self.read(b);
                self.memory[a as usize] = self.read(b);
                self.counter += 4;
            },

            // M[M[B]] <- M[A]
            6 => {
                let b = self.read(b);
                self.memory[b as usize] = self.read(a);
                self.counter += 4;
            },

            // M[A] <- M[B] + M[C]
            7 => {
                let b = self.read(b);
                let c = self.read(c);
                self.memory[a as usize] = b + c;
                self.counter += 4;
            },

            // M[A] <- M[B] - M[C]
            8 => {
                let b = self.read(b);
                let c = self.read(c);
                self.memory[a as usize] = b - c;
                self.counter += 4;
            },

            // M[A] <- M[B] * M[C]
            9 => {
                let b = self.read(b);
                let c = self.read(c);
                self.memory[a as usize] = b * c;
                self.counter += 4;
            },

            // M[A] <- M[B] / M[C]
            10 => {
                let b = self.read(b);
                let c = self.read(c);
                self.memory[a as usize] = b / c;
                self.counter += 4;
            },

            // M[A] <- M[B] % M[C]
            11 => {
                let b = self.read(b);
                let c = self.read(c);
                self.memory[a as usize] = b % c;
                self.counter += 4;
            },

            // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
            12 => {
                let b = self.read(b);
                let c = self.read(c);
                if b < c {
                  self.memory[a as usize] = 1;
                } else {
                  self.memory[a as usize] = 0;
                }
                self.counter += 4;
            },

            // MA[A] <- NOT(M[B] AND M[C])
            13 => {
                let b = self.read(b);
                let c = self.read(c);
                if b > 0 && c > 0 {
                  self.memory[a as usize] = 0;
                } else {
                  self.memory[a as usize] = 1;
                }
                self.counter += 4;
            },

            // Unknown opcode
            _ => {
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Machine;

    #[test]
    fn it_defaults_to_an_infinite_loop() {
        let mut m = Machine::new();

        // Read initial memory and program counter.
        let memory = m.dump().to_vec();
        let counter = m.loc();

        // Step the program twice. If nothing changes, we're in a loop.
        m.step();
        assert_eq!(counter, m.loc());
        assert_eq!(&memory, m.dump());
        m.step();
        assert_eq!(counter, m.loc());
        assert_eq!(&memory, m.dump());
    }

    #[test]
    fn it_runs_opcode_1() {
        // PC <- M[A]
        let mut m = Machine { memory: vec![1, 4, 0, 0, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_then_branch() {
        // If M[B] = 0, then PC <- M[A]
        let mut m = Machine { memory: vec![2, 4, 5, 0, 2, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_else_branch() {
        // If M[B] = 0, then PC <- M[A]
        let mut m = Machine { memory: vec![2, 4, 5, 0, 2, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(0, m.loc());
    }

    #[test]
    fn it_runs_opcode_3() {
        // M[A] <- PC
        let mut m = Machine { memory: vec![3, 4, 0, 0, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![3, 4, 0, 0, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_4() {
        // M[A] <- M[B]
        let mut m = Machine { memory: vec![4, 4, 5, 0, 6, 7], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![4, 4, 5, 0, 7, 7], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_5() {
        // M[A] <- M[M[B]]
        let mut m = Machine { memory: vec![5, 4, 5, 0, 6, 7, 0, 8], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![5, 4, 5, 0, 8, 7, 0, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_6() {
        // M[M[B]] <- M[A]
        let mut m = Machine { memory: vec![6, 4, 5, 0, 8, 6, 7], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![6, 4, 5, 0, 8, 6, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_7() {
        // M[A] <- M[B] + M[C]
        let mut m = Machine { memory: vec![7, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![7, 4, 5, 6, 13, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_8() {
        // M[A] <- M[B] - M[C]
        let mut m = Machine { memory: vec![8, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![8, 4, 5, 6, 9, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_9() {
        // M[A] <- M[B] * M[C]
        let mut m = Machine { memory: vec![9, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![9, 4, 5, 6, 22, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_10() {
        // M[A] <- M[B] / M[C]
        let mut m = Machine { memory: vec![10, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![10, 4, 5, 6, 5, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_11() {
        // M[A] <- M[B] % M[C]
        let mut m = Machine { memory: vec![11, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![11, 4, 5, 6, 1, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_12_then_branch() {
        // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
        let mut m = Machine { memory: vec![12, 4, 5, 6, 2, 8, 9], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![12, 4, 5, 6, 1, 8, 9], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_12_else_branch() {
        // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
        let mut m = Machine { memory: vec![12, 4, 5, 6, 2, 9, 8], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![12, 4, 5, 6, 0, 9, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_false_false_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 0, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 0, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_false_true_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 0, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 0, 1], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_true_false_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 1, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 1, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_true_true_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 1, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 0, 1, 1], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_provides_safe_memory_access_when_stepping() {
        let mut m = Machine { memory: vec![0], counter: 3 };

        m.step();
        assert_eq!(&vec![0, 0, 0, 0, 0, 0, 0], m.dump());
    }
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, BTreeSet};

// https://leetcode.com/problems/tweet-counts-per-frequency/
struct TweetCounts {}

impl TweetCounts {
    fn new() -> Self {
        TweetCounts {}
    }

    fn record_tweet(&mut self, tweet_name: String, time: i32) {
        todo!()
    }

    fn get_tweet_counts_per_frequency(
        &self,
        freq: String,
        tweet_name: String,
        start_time: i32,
        end_time: i32,
    ) -> Vec<i32> {
        match tweet_name.as_str() {
            "minute" => (),
            "hour" => (),
            _ => (),
        };
        todo!()
    }
}

fn main() {
    let mut tweet_counts = TweetCounts::new();
    tweet_counts.record_tweet("tweet3".to_string(), 0);
    tweet_counts.record_tweet("tweet3".to_string(), 60);
    tweet_counts.record_tweet("tweet3".to_string(), 60);
    tweet_counts.record_tweet("tweet3".to_string(), 10);
    tweet_counts.record_tweet("tweet3".to_string(), 10);
    tweet_counts.get_tweet_counts_per_frequency("minute".to_string(), "tweet3".to_string(), 0, 59); // [3]
    tweet_counts.get_tweet_counts_per_frequency("minute".to_string(), "tweet3".to_string(), 0, 60); // [3,2]
    tweet_counts.record_tweet("tweet3".to_string(), 120);
    tweet_counts.get_tweet_counts_per_frequency("hour".to_string(), "tweet3".to_string(), 0, 210);
    // [6]
}
<commit_msg>Update problem 1348<commit_after>use std::collections::{BTreeMap, BTreeSet, HashMap};

// https://leetcode.com/problems/tweet-counts-per-frequency/
struct TweetCounts {
    map: HashMap<String, BTreeMap<i32, i32>>,
}

impl TweetCounts {
    fn new() -> Self {
        TweetCounts {
            map: HashMap::new(),
        }
    }

    fn record_tweet(&mut self, tweet_name: String, time: i32) {
        match self.map.get_mut(&tweet_name) {
            Some(m) => match m.get_mut(&time) {
                Some(m) => {
                    *m += 1;
                }
                None => {
                    m.insert(time, 1);
                }
            },
            None => {
                let mut m: BTreeMap<i32, i32> = BTreeMap::new();
                m.insert(time, 1);
                self.map.insert(tweet_name, m);
            }
        }
    }

    fn get_tweet_counts_per_frequency(
        &self,
        freq: String,
        tweet_name: String,
        start_time: i32,
        end_time: i32,
    ) -> Vec<i32> {
        match tweet_name.as_str() {
            "minute" => {
                let mut time = start_time;
                while time < end_time {
                    time += 60;
                }
            }
            "hour" => (),
            _ => (),
        };
        vec![]
    }
}

fn main() {
    let mut tweet_counts = TweetCounts::new();
    tweet_counts.record_tweet("tweet3".to_string(), 0);
    tweet_counts.record_tweet("tweet3".to_string(), 60);
    tweet_counts.record_tweet("tweet3".to_string(), 60);
    tweet_counts.record_tweet("tweet3".to_string(), 10);
    tweet_counts.record_tweet("tweet3".to_string(), 10);
    tweet_counts.get_tweet_counts_per_frequency("minute".to_string(), "tweet3".to_string(), 0, 59); // [3]
    tweet_counts.get_tweet_counts_per_frequency("minute".to_string(), "tweet3".to_string(), 0, 60); // [3,2]
    tweet_counts.record_tweet("tweet3".to_string(), 120);
    tweet_counts.get_tweet_counts_per_frequency("hour".to_string(), "tweet3".to_string(), 0, 210);
    // [6]
}
<|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.

#[cfg(any(target_os = "macos", target_os = "ios"))]
use core::ptr;
use core::{
    cell::{Cell, UnsafeCell},
    mem::MaybeUninit,
};
use instant::Instant;
use libc;
use std::{thread, time::Duration};

// x32 Linux uses a non-standard type for tv_nsec in timespec.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=16437
#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
#[allow(non_camel_case_types)]
type tv_nsec_t = i64;
#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
#[allow(non_camel_case_types)]
type tv_nsec_t = libc::c_long;

// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
    should_park: Cell<bool>,
    mutex: UnsafeCell<libc::pthread_mutex_t>,
    condvar: UnsafeCell<libc::pthread_cond_t>,
    initialized: Cell<bool>,
}

impl super::ThreadParkerT for ThreadParker {
    type UnparkHandle = UnparkHandle;

    const IS_CHEAP_TO_CONSTRUCT: bool = false;

    #[inline]
    fn new() -> ThreadParker {
        ThreadParker {
            should_park: Cell::new(false),
            mutex: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER),
            condvar: UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER),
            initialized: Cell::new(false),
        }
    }

    #[inline]
    unsafe fn prepare_park(&self) {
        self.should_park.set(true);
        if !self.initialized.get() {
            self.init();
            self.initialized.set(true);
        }
    }

    #[inline]
    unsafe fn timed_out(&self) -> bool {
        // We need to grab the mutex here because another thread may be
        // concurrently executing UnparkHandle::unpark, which is done without
        // holding the queue lock.
        let r = libc::pthread_mutex_lock(self.mutex.get());
        debug_assert_eq!(r, 0);
        let should_park = self.should_park.get();
        let r = libc::pthread_mutex_unlock(self.mutex.get());
        debug_assert_eq!(r, 0);
        should_park
    }

    #[inline]
    unsafe fn park(&self) {
        let r = libc::pthread_mutex_lock(self.mutex.get());
        debug_assert_eq!(r, 0);
        while self.should_park.get() {
            let r = libc::pthread_cond_wait(self.condvar.get(), self.mutex.get());
            debug_assert_eq!(r, 0);
        }
        let r = libc::pthread_mutex_unlock(self.mutex.get());
        debug_assert_eq!(r, 0);
    }

    #[inline]
    unsafe fn park_until(&self, timeout: Instant) -> bool {
        let r = libc::pthread_mutex_lock(self.mutex.get());
        debug_assert_eq!(r, 0);
        while self.should_park.get() {
            let now = Instant::now();
            if timeout <= now {
                let r = libc::pthread_mutex_unlock(self.mutex.get());
                debug_assert_eq!(r, 0);
                return false;
            }

            if let Some(ts) = timeout_to_timespec(timeout - now) {
                let r = libc::pthread_cond_timedwait(self.condvar.get(), self.mutex.get(), &ts);
                if ts.tv_sec < 0 {
                    // On some systems, negative timeouts will return EINVAL. In
                    // that case we won't sleep and will just busy loop instead,
                    // which is the best we can do.
                    debug_assert!(r == 0 || r == libc::ETIMEDOUT || r == libc::EINVAL);
                } else {
                    debug_assert!(r == 0 || r == libc::ETIMEDOUT);
                }
            } else {
                // Timeout calculation overflowed, just sleep indefinitely
                let r = libc::pthread_cond_wait(self.condvar.get(), self.mutex.get());
                debug_assert_eq!(r, 0);
            }
        }
        let r = libc::pthread_mutex_unlock(self.mutex.get());
        debug_assert_eq!(r, 0);
        true
    }

    #[inline]
    unsafe fn unpark_lock(&self) -> UnparkHandle {
        let r = libc::pthread_mutex_lock(self.mutex.get());
        debug_assert_eq!(r, 0);

        UnparkHandle {
            thread_parker: self,
        }
    }
}

impl ThreadParker {
    /// Initializes the condvar to use CLOCK_MONOTONIC instead of CLOCK_REALTIME.
    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
    #[inline]
    unsafe fn init(&self) {}

    /// Initializes the condvar to use CLOCK_MONOTONIC instead of CLOCK_REALTIME.
    #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))]
    #[inline]
    unsafe fn init(&self) {
        let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit();
        let r = libc::pthread_condattr_init(attr.as_mut_ptr());
        debug_assert_eq!(r, 0);
        let r = libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC);
        debug_assert_eq!(r, 0);
        let r = libc::pthread_cond_init(self.condvar.get(), attr.as_ptr());
        debug_assert_eq!(r, 0);
        let r = libc::pthread_condattr_destroy(attr.as_mut_ptr());
        debug_assert_eq!(r, 0);
    }
}

impl Drop for ThreadParker {
    #[inline]
    fn drop(&mut self) {
        // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a
        // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER.
        // Once it is used (locked/unlocked) or pthread_mutex_init() is called,
        // this behaviour no longer occurs. The same applies to condvars.
        unsafe {
            let r = libc::pthread_mutex_destroy(self.mutex.get());
            if cfg!(target_os = "dragonfly") {
                debug_assert!(r == 0 || r == libc::EINVAL);
            } else {
                debug_assert_eq!(r, 0);
            }
            let r = libc::pthread_cond_destroy(self.condvar.get());
            if cfg!(target_os = "dragonfly") {
                debug_assert!(r == 0 || r == libc::EINVAL);
            } else {
                debug_assert_eq!(r, 0);
            }
        }
    }
}

pub struct UnparkHandle {
    thread_parker: *const ThreadParker,
}

impl super::UnparkHandleT for UnparkHandle {
    #[inline]
    unsafe fn unpark(self) {
        (*self.thread_parker).should_park.set(false);

        // We notify while holding the lock here to avoid races with the target
        // thread. In particular, the thread could exit after we unlock the
        // mutex, which would make the condvar access invalid memory.
        let r = libc::pthread_cond_signal((*self.thread_parker).condvar.get());
        debug_assert_eq!(r, 0);
        let r = libc::pthread_mutex_unlock((*self.thread_parker).mutex.get());
        debug_assert_eq!(r, 0);
    }
}

// Returns the current time on the clock used by pthread_cond_t as a timespec.
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[inline]
fn timespec_now() -> libc::timespec {
    let mut now = MaybeUninit::<libc::timeval>::uninit();
    let r = unsafe { libc::gettimeofday(now.as_mut_ptr(), ptr::null_mut()) };
    debug_assert_eq!(r, 0);
    // SAFETY: We know `libc::gettimeofday` has initialized the value.
    let now = unsafe { now.assume_init() };
    libc::timespec {
        tv_sec: now.tv_sec,
        tv_nsec: now.tv_usec as tv_nsec_t * 1000,
    }
}
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
#[inline]
fn timespec_now() -> libc::timespec {
    let mut now = MaybeUninit::<libc::timespec>::uninit();
    let clock = if cfg!(target_os = "android") {
        // Android doesn't support pthread_condattr_setclock, so we need to
        // specify the timeout in CLOCK_REALTIME.
        libc::CLOCK_REALTIME
    } else {
        libc::CLOCK_MONOTONIC
    };
    let r = unsafe { libc::clock_gettime(clock, now.as_mut_ptr()) };
    debug_assert_eq!(r, 0);
    // SAFETY: We know `libc::clock_gettime` has initialized the value.
    unsafe { now.assume_init() }
}

// Converts a relative timeout into an absolute timeout in the clock used by
// pthread_cond_t.
#[inline]
fn timeout_to_timespec(timeout: Duration) -> Option<libc::timespec> {
    // Handle overflows early on
    if timeout.as_secs() > libc::time_t::max_value() as u64 {
        return None;
    }

    let now = timespec_now();
    let mut nsec = now.tv_nsec + timeout.subsec_nanos() as tv_nsec_t;
    let mut sec = now.tv_sec.checked_add(timeout.as_secs() as libc::time_t);
    if nsec >= 1_000_000_000 {
        nsec -= 1_000_000_000;
        sec = sec.and_then(|sec| sec.checked_add(1));
    }

    sec.map(|sec| libc::timespec {
        tv_nsec: nsec,
        tv_sec: sec,
    })
}

#[inline]
pub fn thread_yield() {
    thread::yield_now();
}
<commit_msg>OpenBSD returns EINVAL in the same way as DragonFlyBSD.<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.

#[cfg(any(target_os = "macos", target_os = "ios"))]
use core::ptr;
use core::{
    cell::{Cell, UnsafeCell},
    mem::MaybeUninit,
};
use instant::Instant;
use libc;
use std::{thread, time::Duration};

// x32 Linux uses a non-standard type for tv_nsec in timespec.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=16437
#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
#[allow(non_camel_case_types)]
type tv_nsec_t = i64;
#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
#[allow(non_camel_case_types)]
type tv_nsec_t = libc::c_long;

// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
    should_park: Cell<bool>,
    mutex: UnsafeCell<libc::pthread_mutex_t>,
    condvar: UnsafeCell<libc::pthread_cond_t>,
    initialized: Cell<bool>,
}

impl super::ThreadParkerT for ThreadParker {
    type UnparkHandle = UnparkHandle;

    const IS_CHEAP_TO_CONSTRUCT: bool = false;

    #[inline]
    fn new() -> ThreadParker {
        ThreadParker {
            should_park: Cell::new(false),
            mutex: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER),
            condvar: UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER),
            initialized: Cell::new(false),
        }
    }

    #[inline]
    unsafe fn prepare_park(&self) {
        self.should_park.set(true);
        if !self.initialized.get() {
            self.init();
            self.initialized.set(true);
        }
    }

    #[inline]
    unsafe fn timed_out(&self) -> bool {
        // We need to grab the mutex here because another thread may be
        // concurrently executing UnparkHandle::unpark, which is done without
        // holding the queue lock.
        let r = libc::pthread_mutex_lock(self.mutex.get());
        debug_assert_eq!(r, 0);
        let should_park = self.should_park.get();
        let r = libc::pthread_mutex_unlock(self.mutex.get());
        debug_assert_eq!(r, 0);
        should_park
    }

    #[inline]
    unsafe fn park(&self) {
        let r = libc::pthread_mutex_lock(self.mutex.get());
        debug_assert_eq!(r, 0);
        while self.should_park.get() {
            let r = libc::pthread_cond_wait(self.condvar.get(), self.mutex.get());
            debug_assert_eq!(r, 0);
        }
        let r = libc::pthread_mutex_unlock(self.mutex.get());
        debug_assert_eq!(r, 0);
    }

    #[inline]
    unsafe fn park_until(&self, timeout: Instant) -> bool {
        let r = libc::pthread_mutex_lock(self.mutex.get());
        debug_assert_eq!(r, 0);
        while self.should_park.get() {
            let now = Instant::now();
            if timeout <= now {
                let r = libc::pthread_mutex_unlock(self.mutex.get());
                debug_assert_eq!(r, 0);
                return false;
            }

            if let Some(ts) = timeout_to_timespec(timeout - now) {
                let r = libc::pthread_cond_timedwait(self.condvar.get(), self.mutex.get(), &ts);
                if ts.tv_sec < 0 {
                    // On some systems, negative timeouts will return EINVAL. In
                    // that case we won't sleep and will just busy loop instead,
                    // which is the best we can do.
                    debug_assert!(r == 0 || r == libc::ETIMEDOUT || r == libc::EINVAL);
                } else {
                    debug_assert!(r == 0 || r == libc::ETIMEDOUT);
                }
            } else {
                // Timeout calculation overflowed, just sleep indefinitely
                let r = libc::pthread_cond_wait(self.condvar.get(), self.mutex.get());
                debug_assert_eq!(r, 0);
            }
        }
        let r = libc::pthread_mutex_unlock(self.mutex.get());
        debug_assert_eq!(r, 0);
        true
    }

    #[inline]
    unsafe fn unpark_lock(&self) -> UnparkHandle {
        let r = libc::pthread_mutex_lock(self.mutex.get());
        debug_assert_eq!(r, 0);

        UnparkHandle {
            thread_parker: self,
        }
    }
}

impl ThreadParker {
    /// Initializes the condvar to use CLOCK_MONOTONIC instead of CLOCK_REALTIME.
    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
    #[inline]
    unsafe fn init(&self) {}

    /// Initializes the condvar to use CLOCK_MONOTONIC instead of CLOCK_REALTIME.
    #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))]
    #[inline]
    unsafe fn init(&self) {
        let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit();
        let r = libc::pthread_condattr_init(attr.as_mut_ptr());
        debug_assert_eq!(r, 0);
        let r = libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC);
        debug_assert_eq!(r, 0);
        let r = libc::pthread_cond_init(self.condvar.get(), attr.as_ptr());
        debug_assert_eq!(r, 0);
        let r = libc::pthread_condattr_destroy(attr.as_mut_ptr());
        debug_assert_eq!(r, 0);
    }
}

impl Drop for ThreadParker {
    #[inline]
    fn drop(&mut self) {
        // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a
        // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER.
        // Once it is used (locked/unlocked) or pthread_mutex_init() is called,
        // this behaviour no longer occurs. The same applies to condvars.
        unsafe {
            let r = libc::pthread_mutex_destroy(self.mutex.get());
            if cfg!(any(target_os = "dragonfly", target_os = "openbsd")) {
                debug_assert!(r == 0 || r == libc::EINVAL);
            } else {
                debug_assert_eq!(r, 0);
            }
            let r = libc::pthread_cond_destroy(self.condvar.get());
            if cfg!(any(target_os = "dragonfly", target_os = "openbsd")) {
                debug_assert!(r == 0 || r == libc::EINVAL);
            } else {
                debug_assert_eq!(r, 0);
            }
        }
    }
}

pub struct UnparkHandle {
    thread_parker: *const ThreadParker,
}

impl super::UnparkHandleT for UnparkHandle {
    #[inline]
    unsafe fn unpark(self) {
        (*self.thread_parker).should_park.set(false);

        // We notify while holding the lock here to avoid races with the target
        // thread. In particular, the thread could exit after we unlock the
        // mutex, which would make the condvar access invalid memory.
        let r = libc::pthread_cond_signal((*self.thread_parker).condvar.get());
        debug_assert_eq!(r, 0);
        let r = libc::pthread_mutex_unlock((*self.thread_parker).mutex.get());
        debug_assert_eq!(r, 0);
    }
}

// Returns the current time on the clock used by pthread_cond_t as a timespec.
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[inline]
fn timespec_now() -> libc::timespec {
    let mut now = MaybeUninit::<libc::timeval>::uninit();
    let r = unsafe { libc::gettimeofday(now.as_mut_ptr(), ptr::null_mut()) };
    debug_assert_eq!(r, 0);
    // SAFETY: We know `libc::gettimeofday` has initialized the value.
    let now = unsafe { now.assume_init() };
    libc::timespec {
        tv_sec: now.tv_sec,
        tv_nsec: now.tv_usec as tv_nsec_t * 1000,
    }
}
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
#[inline]
fn timespec_now() -> libc::timespec {
    let mut now = MaybeUninit::<libc::timespec>::uninit();
    let clock = if cfg!(target_os = "android") {
        // Android doesn't support pthread_condattr_setclock, so we need to
        // specify the timeout in CLOCK_REALTIME.
        libc::CLOCK_REALTIME
    } else {
        libc::CLOCK_MONOTONIC
    };
    let r = unsafe { libc::clock_gettime(clock, now.as_mut_ptr()) };
    debug_assert_eq!(r, 0);
    // SAFETY: We know `libc::clock_gettime` has initialized the value.
    unsafe { now.assume_init() }
}

// Converts a relative timeout into an absolute timeout in the clock used by
// pthread_cond_t.
#[inline]
fn timeout_to_timespec(timeout: Duration) -> Option<libc::timespec> {
    // Handle overflows early on
    if timeout.as_secs() > libc::time_t::max_value() as u64 {
        return None;
    }

    let now = timespec_now();
    let mut nsec = now.tv_nsec + timeout.subsec_nanos() as tv_nsec_t;
    let mut sec = now.tv_sec.checked_add(timeout.as_secs() as libc::time_t);
    if nsec >= 1_000_000_000 {
        nsec -= 1_000_000_000;
        sec = sec.and_then(|sec| sec.checked_add(1));
    }

    sec.map(|sec| libc::timespec {
        tv_nsec: nsec,
        tv_sec: sec,
    })
}

#[inline]
pub fn thread_yield() {
    thread::yield_now();
}
<|endoftext|>


<commit_before>
use util;
use std;
use std::error::Error;

pub type Result<T> = std::result::Result<T,String>;

/// A token.
#[derive(Clone,Debug,PartialEq,Eq)]
pub enum Token
{
    Word(String),

    String(String),
    // TODO: use BigNum
    Integer(i64),

    Symbol(String),

    NewLine,
    EOF,
}

impl Token
{
    pub fn word<S>(word: S) -> Self
        where S: Into<String> {
        Token::Word(word.into())
    }

    pub fn string<S>(string: S) -> Self
        where S: Into<String> {
        Token::String(string.into())
    }

    pub fn integer<I>(integer: I) -> Self
        where I: Into<i64> {
        Token::Integer(integer.into())
    }

    pub fn symbol<S>(symbol: S) -> Self
        where S: Into<String> {
        Token::Symbol(symbol.into())
    }

    pub fn new_line() -> Self {
        Token::NewLine
    }

    pub fn eof() -> Self {
        Token::EOF
    }
}

impl std::fmt::Display for Token
{
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            &Token::Word(ref w) => write!(fmt, "{}", w),
            &Token::String(ref s) => write!(fmt, "\"{}\"", s),
            &Token::Integer(ref i) => write!(fmt, "{}", i),
            &Token::Symbol(ref s) => write!(fmt, "{}", s),
            &Token::NewLine => write!(fmt, "new line"),
            &Token::EOF => write!(fmt, "EOF"),
        }
    }
}

/// An iterator over a set of characters.
///
/// This type abstracts over another iterator of characters,
/// making sure that the yielded characters will have a specific
/// format.
///
/// * There will always be a new line (`\n`) before the end of file.
pub struct Characters<I: Iterator<Item=char>>
{
    it: std::iter::Peekable<I>,
    finished: bool,
    peek_buf: Option<char>,
}

impl<I> Characters<I>
    where I: Iterator<Item=char>
{
    pub fn new(it: I) -> Self {
        Characters {
            it: it.peekable(),
            finished: false,
            peek_buf: None,
        }
    }

    pub fn peek(&mut self) -> Option<char> {
        if self.peek_buf.is_none() {
            self.peek_buf = self.next();
        }

        self.peek_buf
    }

    pub fn eat(&mut self) {
        self.next();
    }

    pub fn eat_while<P>(&mut self, predicate: P)
        where P: FnMut(char) -> bool {
        self.consume_while(predicate);
    }

    pub fn consume_while<P>(&mut self, mut predicate: P)
        -> std::vec::IntoIter<char>
        where P: FnMut(char) -> bool {
        let mut result = Vec::new();

        loop {
            let c = match self.peek() {
                Some(c) => c,
                None => break,
            };

            if predicate(c) {
                result.push(self.next().unwrap());
            } else {
                break;
            }
        }

        result.into_iter()
    }
}

impl<I> Iterator for Characters<I>
    where I: Iterator<Item=char>
{
    type Item = char;

    fn next(&mut self) -> Option<char> {
        if self.peek_buf.is_some() {
            let c = self.peek_buf.unwrap();
            self.peek_buf = None;
            return Some(c);
        }

        match self.it.next() {
            Some(c) => Some(c),
            None => {
                if self.finished {
                    None
                } else { // When we first reach the EOF
                    self.finished = true;
                    Some('\n')
                }
            },
        }
    }
}

pub struct Tokenizer<I: Iterator<Item=char>>
{
    chars: Characters<I>,
    finished: bool,
}

impl<I> Tokenizer<I>
    where I: Iterator<Item=char>
{
    pub fn new(chars: I) -> Self {
        Tokenizer {
            chars: Characters::new(chars),
            finished: false,
        }
    }

    fn eat_whitespace(&mut self) {
        self.chars.eat_while(|c| c.is_whitespace() && c != '\n')
    }

    fn next_string(&mut self) -> Option<Result<Token>> {
        self.assert('"');
        let string = self.chars.consume_while(|c| c != '\"');
        self.assert('"');

        Some(Ok(Token::String(string.collect())))
    }

    fn next_integer(&mut self) -> Option<Result<Token>> {
        let string: String = self.chars.consume_while(|c| c.is_numeric()).collect();

        let int = match i64::from_str_radix(&string, 10) {
            Ok(int) => int,
            Err(e) => return Some(Err(format!("Could not parse integer: {}",
                                              e.description()))),
        };

        Some(Ok(Token::Integer(int)))
    }

    fn next_word(&mut self) -> Option<Result<Token>> {
        let word: String = self.chars.consume_while(internal::can_word_contain).collect();

        Some(Ok(Token::Word(word)))
    }

    fn next_symbol(&mut self) -> Option<Result<Token>> {
        unimplemented!();
    }

    fn assert(&mut self, expected: char) -> char {
        self.expect(expected).expect("unexpected character")
    }

    fn expect(&mut self, expected: char) -> Result<char> {
        // TODO: more specific error message
        self.expect_one_of(&[expected])
    }

    fn assert_one_of(&mut self, expected: &[char]) -> char {
        self.expect_one_of(expected)
            .expect("unexpected character")
    }

    fn expect_one_of(&mut self, expected: &[char]) -> Result<char> {
        let expected_str = util::comma_separated_values(expected.iter());

        let next = match self.chars.next() {
            Some(c) => c,
            None => {
                return Err(format!("expected one of {} but got nothing", expected_str))
            },
        };

        if expected.iter().any(|&c| c == next) {
            Ok(next)
        } else {
            Err(format!("Expected one of {} but got {}", expected_str, next))
        }
    }
}

impl<I> Iterator for Tokenizer<I>
    where I: Iterator<Item=char>
{
    type Item = Result<Token>;

    fn next(&mut self) -> Option<Result<Token>> {
        self.eat_whitespace();

        let first_char = match self.chars.peek() {
            Some(c) => c,

            // If there are no tokens left, return EOF if
            // we haven't already, or None otherwise.
            None => {
                if self.finished {
                    return None;
                } else {
                    self.finished = true;
                    return Some(Ok(Token::eof()));
                }
            },
        };

        if first_char == '"' {
            self.next_string()
        } else if first_char == '\n' {
            self.chars.eat();
            Some(Ok(Token::new_line()))
        } else if first_char.is_numeric() {
            self.next_integer()
        } else if internal::can_word_start_with(first_char) {
            self.next_word()
        } else {
            self.next_symbol()
        }
    }
}

mod internal
{
    pub fn can_word_start_with(c: char) -> bool {
        c.is_alphabetic() || c == '_'
    }

    pub fn can_word_contain(c: char) -> bool {
        can_word_start_with(c) || c.is_numeric()
    }
}

mod test
{
    use super::{Token,Tokenizer};

    macro_rules! expect_tokenize_into {
        // TODO: make the macro take several arguments
        // for several outputs
        ($input:expr => $( $output:expr ),* ) => {
            {
                let mut tokenizer = Tokenizer::new($input.chars());

                $(
                    let token = tokenizer.next().unwrap().unwrap();
                    assert!($output == token,
                            format!("expected {} but got {}",
                                    $output, token));
                )*
            }
        }
    }

    #[test]
    fn test_string() {
        expect_tokenize_into!("\"hello\"" =>  Token::string("hello"),
                                              Token::new_line(),
                                              Token::eof());

        expect_tokenize_into!("\"hello abc\"" => Token::string("hello abc"),
                                                 Token::new_line(),
                                                 Token::eof());

        expect_tokenize_into!("\"hello world\"  \"it is me\"" =>
                              Token::string("hello world"),
                              Token::string("it is me"),
                              Token::new_line(),
                              Token::eof());
    }

    #[test]
    fn test_integer() {
        expect_tokenize_into!("123" => Token::integer(123),
                                       Token::new_line(),
                                       Token::eof());

        expect_tokenize_into!("0982" => Token::integer(982),
                                        Token::new_line(),
                                        Token::eof());

        expect_tokenize_into!("333 662" => Token::integer(333),
                                           Token::integer(662),
                                           Token::new_line(),
                                           Token::eof());

        expect_tokenize_into!("1 2 3 4" => Token::integer(1),
                                           Token::integer(2),
                                           Token::integer(3),
                                           Token::integer(4),
                                           Token::new_line(),
                                           Token::eof());
    }

    #[test]
    fn test_word() {
        expect_tokenize_into!("hello" => Token::word("hello"));

        expect_tokenize_into!("ab cd" => Token::word("ab"),
                                         Token::word("cd"),
                                         Token::new_line(),
                                         Token::eof());

        expect_tokenize_into!("a b c d" => Token::word("a"),
                                           Token::word("b"),
                                           Token::word("c"),
                                           Token::word("d"),
                                           Token::new_line(),
                                           Token::eof());
    }

    #[test]
    fn test_multiple() {
        expect_tokenize_into!("12 bark \"earth\"" => Token::integer(12),
                                                     Token::word("bark"),
                                                     Token::string("earth"),
                                                     Token::new_line(),
                                                     Token::eof());

        expect_tokenize_into!("a      23 gg \"a\"" => Token::word("a"),
                                                      Token::integer(23),
                                                      Token::word("gg"),
                                                      Token::string("a"),
                                                      Token::new_line(),
                                                      Token::eof());
    }

    #[test]
    fn test_whitespace() {
        expect_tokenize_into!("a\tb\t123\n\"qwer\"\n" => Token::word("a"),
                                                         Token::word("b"),
                                                         Token::integer(123),
                                                         Token::new_line(),
                                                         Token::string("qwer"),
                                                         Token::new_line(),
                                                         Token::new_line(),
                                                         Token::eof());
    }
}
<commit_msg>[IR] Added comment support to tokenizer<commit_after>
use util;
use std;
use std::error::Error;

pub type Result<T> = std::result::Result<T,String>;

/// A token.
#[derive(Clone,Debug,PartialEq,Eq)]
pub enum Token
{
    /// A word.
    Word(String),
    /// A string literal.
    String(String),
    /// An integer literal.
    // TODO: use BigNum
    Integer(i64),
    /// A comment.
    ///
    /// If the comment is inline, it existed on the same line
    /// as the previous statement.
    ///
    /// For example
    ///
    /// ```
    /// add 2, 4 ; inline comment goes here
    /// ```
    Comment {
        inline: bool,
        text: String,
    },
    /// A symbol.
    Symbol(String),
    /// A new line.
    NewLine,
    /// End of file.
    /// Will always be yielded as the last
    /// token.
    EOF,
}

impl Token
{
    pub fn word<S>(word: S) -> Self
        where S: Into<String> {
        Token::Word(word.into())
    }

    pub fn string<S>(string: S) -> Self
        where S: Into<String> {
        Token::String(string.into())
    }

    pub fn integer<I>(integer: I) -> Self
        where I: Into<i64> {
        Token::Integer(integer.into())
    }

    pub fn comment<S>(text: S) -> Self
        where S: Into<String> {
        Token::Comment {
            inline: false,
            text: text.into(),
        }
    }

    pub fn inline_comment<S>(text: S) -> Self
        where S: Into<String> {
        Token::Comment {
            inline: true,
            text: text.into(),
        }
    }

    pub fn symbol<S>(symbol: S) -> Self
        where S: Into<String> {
        Token::Symbol(symbol.into())
    }

    pub fn new_line() -> Self {
        Token::NewLine
    }

    pub fn eof() -> Self {
        Token::EOF
    }
}

impl std::fmt::Display for Token
{
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            &Token::Word(ref w) => write!(fmt, "{}", w),
            &Token::String(ref s) => write!(fmt, "\"{}\"", s),
            &Token::Integer(ref i) => write!(fmt, "{}", i),
            &Token::Symbol(ref s) => write!(fmt, "{}", s),
            &Token::Comment { ref text, .. } => write!(fmt, " {}", text),
            &Token::NewLine => write!(fmt, "new line"),
            &Token::EOF => write!(fmt, "EOF"),
        }
    }
}

/// An iterator over a set of characters.
///
/// This type abstracts over another iterator of characters,
/// making sure that the yielded characters will have a specific
/// format.
///
/// * There will always be a new line (`\n`) before the end of file.
pub struct Characters<I: Iterator<Item=char>>
{
    it: std::iter::Peekable<I>,
    finished: bool,
    peek_buf: Option<char>,
}

impl<I> Characters<I>
    where I: Iterator<Item=char>
{
    pub fn new(it: I) -> Self {
        Characters {
            it: it.peekable(),
            finished: false,
            peek_buf: None,
        }
    }

    pub fn peek(&mut self) -> Option<char> {
        if self.peek_buf.is_none() {
            self.peek_buf = self.next();
        }

        self.peek_buf
    }

    pub fn eat(&mut self) {
        self.next();
    }

    pub fn eat_while<P>(&mut self, predicate: P)
        where P: FnMut(char) -> bool {
        self.consume_while(predicate);
    }

    pub fn consume_while<P>(&mut self, mut predicate: P)
        -> std::vec::IntoIter<char>
        where P: FnMut(char) -> bool {
        let mut result = Vec::new();

        loop {
            let c = match self.peek() {
                Some(c) => c,
                None => break,
            };

            if predicate(c) {
                result.push(self.next().unwrap());
            } else {
                break;
            }
        }

        result.into_iter()
    }
}

impl<I> Iterator for Characters<I>
    where I: Iterator<Item=char>
{
    type Item = char;

    fn next(&mut self) -> Option<char> {
        if self.peek_buf.is_some() {
            let c = self.peek_buf.unwrap();
            self.peek_buf = None;
            return Some(c);
        }

        match self.it.next() {
            Some(c) => Some(c),
            None => {
                if self.finished {
                    None
                } else { // When we first reach the EOF
                    self.finished = true;
                    Some('\n')
                }
            },
        }
    }
}

pub struct Tokenizer<I: Iterator<Item=char>>
{
    chars: Characters<I>,

    finished: bool,
    preserve_comments: bool,
}

impl<I> Tokenizer<I>
    where I: Iterator<Item=char>
{
    pub fn new(chars: I) -> Self {
        Tokenizer {
            chars: Characters::new(chars),
            finished: false,
            preserve_comments: false,
        }
    }

    /// Allows the tokenizer to preserve comments it tokenizes.
    pub fn preserve_comments(mut self) -> Self {
        self.preserve_comments = true;
        self
    }

    fn eat_whitespace(&mut self) {
        self.chars.eat_while(|c| c.is_whitespace() && c != '\n')
    }

    fn next_string(&mut self) -> Option<Result<Token>> {
        self.assert('"');
        let string = self.chars.consume_while(|c| c != '\"');
        self.assert('"');

        Some(Ok(Token::String(string.collect())))
    }

    fn next_integer(&mut self) -> Option<Result<Token>> {
        let string: String = self.chars.consume_while(|c| c.is_numeric()).collect();

        let int = match i64::from_str_radix(&string, 10) {
            Ok(int) => int,
            Err(e) => return Some(Err(format!("Could not parse integer: {}",
                                              e.description()))),
        };

        Some(Ok(Token::Integer(int)))
    }

    fn next_word(&mut self) -> Option<Result<Token>> {
        let word: String = self.chars.consume_while(internal::can_word_contain).collect();

        Some(Ok(Token::Word(word)))
    }

    fn next_symbol(&mut self) -> Option<Result<Token>> {
        unimplemented!();
    }

    fn next_comment(&mut self) -> Option<Result<Token>> {
        self.assert(';');
        let text: String = self.chars.consume_while(|c| c != '\n').collect();

        Some(Ok(Token::comment(text)))
    }

    fn eat_next_comment(&mut self) -> Option<Result<()>> {
        self.next_comment().map(|result| result.map(|_| ()))
    }

    fn assert(&mut self, expected: char) -> char {
        self.expect(expected).expect("unexpected character")
    }

    fn expect(&mut self, expected: char) -> Result<char> {
        // TODO: more specific error message
        self.expect_one_of(&[expected])
    }

    fn expect_one_of(&mut self, expected: &[char]) -> Result<char> {
        let expected_str = util::comma_separated_values(expected.iter());

        let next = match self.chars.next() {
            Some(c) => c,
            None => {
                return Err(format!("expected one of {} but got nothing", expected_str))
            },
        };

        if expected.iter().any(|&c| c == next) {
            Ok(next)
        } else {
            Err(format!("Expected one of {} but got {}", expected_str, next))
        }
    }
}

impl<I> Iterator for Tokenizer<I>
    where I: Iterator<Item=char>
{
    type Item = Result<Token>;

    fn next(&mut self) -> Option<Result<Token>> {
        self.eat_whitespace();

        let first_char = match self.chars.peek() {
            Some(c) => c,

            // If there are no tokens left, return EOF if
            // we haven't already, or None otherwise.
            None => {
                if self.finished {
                    return None;
                } else {
                    self.finished = true;
                    return Some(Ok(Token::eof()));
                }
            },
        };

        if first_char == '"' {
            self.next_string()
        } else if first_char == '\n' {
            self.chars.eat();
            Some(Ok(Token::new_line()))
        } else if first_char == ';' {
            if self.preserve_comments {
                self.next_comment()
            } else {

                // TODO: This could be nicer
                match self.eat_next_comment() {
                    Some(Ok(..)) => (),
                    Some(Err(e)) => return Some(Err(e)),
                    None => panic!("expected a comment to be parsed"),
                }

                // TODO: fix needless recursion
                self.next()
            }
        } else if first_char.is_numeric() {
            self.next_integer()
        } else if internal::can_word_start_with(first_char) {
            self.next_word()
        } else {
            self.next_symbol()
        }
    }
}

mod internal
{
    pub fn can_word_start_with(c: char) -> bool {
        c.is_alphabetic() || c == '_'
    }

    pub fn can_word_contain(c: char) -> bool {
        can_word_start_with(c) || c.is_numeric()
    }
}

mod test
{
    use super::{Token,Tokenizer};

    /// Expects a mapping from a string of tokens into
    /// a list of tokens with the default tokenizer.
    macro_rules! expect_mapping {
        ($input:expr => $( $output:expr ),* ) => {
            expect_mapping_with!(Tokenizer::new($input.chars()) =>
                                 $( $output ),*);
        }
    }

    /// Expects a mapping from a string of tokens into
    /// a list of tokens, given a specific tokenizer.
    macro_rules! expect_mapping_with {
        // TODO: make the macro take several arguments
        // for several outputs
        ($tokenizer:expr => $( $output:expr ),* ) => {
            {
                let mut tokenizer = $tokenizer;

                $(
                    let token = tokenizer.next().unwrap().unwrap();
                    assert!($output == token,
                            format!("expected {} but got {}",
                                    $output, token));
                )*
            }
        }
    }

    #[test]
    fn test_string() {
        expect_mapping!("\"hello\"" =>  Token::string("hello"),
                                        Token::new_line(),
                                        Token::eof());

        expect_mapping!("\"hello abc\"" => Token::string("hello abc"),
                                           Token::new_line(),
                                           Token::eof());

        expect_mapping!("\"hello world\"  \"it is me\"" =>
                        Token::string("hello world"),
                        Token::string("it is me"),
                        Token::new_line(),
                        Token::eof());
    }

    #[test]
    fn test_integer() {
        expect_mapping!("123" => Token::integer(123),
                                 Token::new_line(),
                                 Token::eof());

        expect_mapping!("0982" => Token::integer(982),
                                  Token::new_line(),
                                  Token::eof());

        expect_mapping!("333 662" => Token::integer(333),
                                     Token::integer(662),
                                     Token::new_line(),
                                     Token::eof());

        expect_mapping!("1 2 3 4" => Token::integer(1),
                                     Token::integer(2),
                                     Token::integer(3),
                                     Token::integer(4),
                                     Token::new_line(),
                                     Token::eof());
    }

    #[test]
    fn test_word() {
        expect_mapping!("hello" => Token::word("hello"));

        expect_mapping!("ab cd" => Token::word("ab"),
                                   Token::word("cd"),
                                   Token::new_line(),
                                   Token::eof());

        expect_mapping!("a b c d" => Token::word("a"),
                                     Token::word("b"),
                                     Token::word("c"),
                                     Token::word("d"),
                                     Token::new_line(),
                                     Token::eof());
    }

    #[test]
    fn test_comments_not_preserved_by_default() {
        expect_mapping!("hello ; there" => Token::word("hello"),
                                           Token::new_line(),
                                           Token::eof());

        expect_mapping!(";why hello" => Token::new_line(),
                                        Token::eof());
    }

    #[test]
    fn test_comments() {
        expect_mapping_with!(Tokenizer::new("hello world ; this is me".chars())
                             .preserve_comments()
                             => Token::word("hello"),
                                Token::word("world"),
                                Token::comment(" this is me"),
                                Token::new_line(),
                                Token::eof());

        expect_mapping_with!(Tokenizer::new(";this is a test".chars())
                             .preserve_comments()
                             => Token::comment("this is a test"),
                                Token::new_line(),
                                Token::eof());
    }

    #[test]
    fn test_multiple() {
        expect_mapping!("12 bark \"earth\"" => Token::integer(12),
                                               Token::word("bark"),
                                               Token::string("earth"),
                                               Token::new_line(),
                                               Token::eof());

        expect_mapping!("a      23 gg \"a\"" => Token::word("a"),
                                                Token::integer(23),
                                                Token::word("gg"),
                                                Token::string("a"),
                                                Token::new_line(),
                                                Token::eof());
    }

    #[test]
    fn test_whitespace() {
        expect_mapping!("a\tb\t123\n\"qwer\"\n" => Token::word("a"),
                                                   Token::word("b"),
                                                   Token::integer(123),
                                                   Token::new_line(),
                                                   Token::string("qwer"),
                                                   Token::new_line(),
                                                   Token::new_line(),
                                                   Token::eof());
    }
}
<|endoftext|>