<commit_before>/// The Toml Set extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueSetExt<'doc> {

    /// Extension function for setting a value in the current toml::Value document
    /// using a custom seperator
    ///
    /// # Semantics
    ///
    /// The function _never_ creates intermediate data structures (Tables or Arrays) in the
    /// document.
    ///
    /// # Return value
    ///
    /// * If the set operation worked correctly, `Ok(None)` is returned.
    /// * If the set operation replaced an existing value `Ok(Some(old_value))` is returned
    /// * On failure, `Err(e)` is returned:
    ///     * If the query is `"a.b.c"` but there is no table `"b"`: error
    ///     * If the query is `"a.b.[0]"` but "`b"` is not an array: error
    ///     * If the query is `"a.b.[3]"` but the array at "`b"` has no index `3`: error
    ///     * etc.
    ///
    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>>;

    /// Extension function for setting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueSetExt::set_with_seperator`
    fn set(&mut self, query: &String, value: Value) -> Result<Option<Value>> {
        self.set_with_seperator(query, '.', value)
    }

}

impl<'doc> TomlValueSetExt<'doc> for Value {

    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

    }

}

#[cfg(test)]
mod test {
    use super::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_set_with_seperator_into_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_array() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nested_table() {
        let mut toml : Value = toml_from_str(r#"
        [a.b.c]
        d = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("a.b.c.d"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let a = t.get("a");
                assert!(a.is_some());

                let a = a.unwrap();
                assert!(is_match!(a, &Value::Table(_)));
                match a {
                    &Value::Table(ref a) => {
                        assert!(!a.is_empty());

                        let b_tab = a.get("b");
                        assert!(b_tab.is_some());

                        let b_tab = b_tab.unwrap();
                        assert!(is_match!(b_tab, &Value::Table(_)));
                        match b_tab {
                            &Value::Table(ref b) => {
                                assert!(!b.is_empty());

                                let c_tab = b.get("c");
                                assert!(c_tab.is_some());

                                let c_tab = c_tab.unwrap();
                                assert!(is_match!(c_tab, &Value::Table(_)));
                                match c_tab {
                                    &Value::Table(ref c) => {
                                        assert!(!c.is_empty());

                                        let d = c.get("d");
                                        assert!(d.is_some());

                                        let d = d.unwrap();
                                        assert!(is_match!(d, &Value::Integer(1)));
                                    },
                                    _ => panic!("What just happenend?"),
                                }
                            },
                            _ => panic!("What just happenend?"),
                        }
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

}

<commit_msg>Impl set_with_seperator to fix test_set_with_seperator_into_table<commit_after>/// The Toml Set extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use tokenizer::Token;
use error::*;

pub trait TomlValueSetExt<'doc> {

    /// Extension function for setting a value in the current toml::Value document
    /// using a custom seperator
    ///
    /// # Semantics
    ///
    /// The function _never_ creates intermediate data structures (Tables or Arrays) in the
    /// document.
    ///
    /// # Return value
    ///
    /// * If the set operation worked correctly, `Ok(None)` is returned.
    /// * If the set operation replaced an existing value `Ok(Some(old_value))` is returned
    /// * On failure, `Err(e)` is returned:
    ///     * If the query is `"a.b.c"` but there is no table `"b"`: error
    ///     * If the query is `"a.b.[0]"` but "`b"` is not an array: error
    ///     * If the query is `"a.b.[3]"` but the array at "`b"` has no index `3`: error
    ///     * etc.
    ///
    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>>;

    /// Extension function for setting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueSetExt::set_with_seperator`
    fn set(&mut self, query: &String, value: Value) -> Result<Option<Value>> {
        self.set_with_seperator(query, '.', value)
    }

}

impl<'doc> TomlValueSetExt<'doc> for Value {

    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last = tokens.pop_last();
        let last = last.unwrap();

        match *last {
            Token::Identifier { ident, .. } => {
                let mut val = try!(resolve(self, &tokens));
                match val {
                    &mut Value::Table(ref mut t) => {
                        Ok(t.insert(ident, value))
                    }
                    _ => unimplemented!()
                }
            }

            _ => unimplemented!(),
        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_set_with_seperator_into_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_array() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nested_table() {
        let mut toml : Value = toml_from_str(r#"
        [a.b.c]
        d = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("a.b.c.d"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let a = t.get("a");
                assert!(a.is_some());

                let a = a.unwrap();
                assert!(is_match!(a, &Value::Table(_)));
                match a {
                    &Value::Table(ref a) => {
                        assert!(!a.is_empty());

                        let b_tab = a.get("b");
                        assert!(b_tab.is_some());

                        let b_tab = b_tab.unwrap();
                        assert!(is_match!(b_tab, &Value::Table(_)));
                        match b_tab {
                            &Value::Table(ref b) => {
                                assert!(!b.is_empty());

                                let c_tab = b.get("c");
                                assert!(c_tab.is_some());

                                let c_tab = c_tab.unwrap();
                                assert!(is_match!(c_tab, &Value::Table(_)));
                                match c_tab {
                                    &Value::Table(ref c) => {
                                        assert!(!c.is_empty());

                                        let d = c.get("d");
                                        assert!(d.is_some());

                                        let d = d.unwrap();
                                        assert!(is_match!(d, &Value::Integer(1)));
                                    },
                                    _ => panic!("What just happenend?"),
                                }
                            },
                            _ => panic!("What just happenend?"),
                        }
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

}

<|endoftext|>


<commit_before>/**
 * A structure shared across REPL instances for storing history
 * such as statements and view items. I wish the AST was sendable.
 */
struct Repl {
    prompt: ~str,
    binary: ~str,
    running: bool,
    view_items: ~str,
    stmts: ~str
}

/// A utility function that hands off a pretty printer to a callback.
fn with_pp(intr: @token::ident_interner,
           cb: fn(pprust::ps, io::Writer)) -> ~str {
    do io::with_str_writer |writer| {
        let pp = pprust::rust_printer(writer, intr);

        cb(pp, writer);
        pp::eof(pp.s);
    }
}

/**
 * The AST (or the rest of rustc) are not sendable yet,
 * so recorded things are printed to strings. A terrible hack that
 * needs changes to rustc in order to be outed. This is unfortunately
 * going to cause the REPL to regress in parser performance,
 * because it has to parse the statements and view_items on each
 * input.
 */
fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl {
    let view_items = if blk.node.view_items.len() > 0 {
        let new_view_items = do with_pp(intr) |pp, writer| {
            for blk.node.view_items.each |view_item| {
                pprust::print_view_item(pp, *view_item);
                writer.write_line(~"");
            }
        };

        debug!("new view items %s", new_view_items);

        repl.view_items + "\n" + new_view_items
    } else { repl.view_items };
    let stmts = if blk.node.stmts.len() > 0 {
        let new_stmts = do with_pp(intr) |pp, writer| {
            for blk.node.stmts.each |stmt| {
                match stmt.node {
                    ast::stmt_decl(*) => {
                        pprust::print_stmt(pp, **stmt);
                        writer.write_line(~"");
                    }
                    ast::stmt_expr(expr, _) | ast::stmt_semi(expr, _) => {
                        match expr.node {
                            ast::expr_assign(*) |
                            ast::expr_assign_op(*) |
                            ast::expr_swap(*) => {
                                pprust::print_stmt(pp, **stmt);
                                writer.write_line(~"");
                            }
                            _ => {}
                        }
                    }
                }
            }
        };

        debug!("new stmts %s", new_stmts);

        repl.stmts + "\n" + new_stmts
    } else { repl.stmts };

    Repl{
        view_items: view_items,
        stmts: stmts,
        .. repl
    }
}

/// Run an input string in a Repl, returning the new Repl.
fn run(repl: Repl, input: ~str) -> Repl {
    let options: @session::options = @{
        crate_type: session::unknown_crate,
        binary: repl.binary,
        addl_lib_search_paths: ~[os::getcwd()],
        .. *session::basic_options()
    };

    debug!("building driver input");
    let head = include_str!("wrapper.rs");
    let foot = fmt!("%s\nfn main() {\n%s\n\nprint({\n%s\n})\n}",
                    repl.view_items, repl.stmts, input);
    let wrapped = driver::str_input(head + foot);

    debug!("inputting %s", head + foot);

    debug!("building a driver session");
    let sess = driver::build_session(options, diagnostic::emit);

    debug!("building driver configuration");
    let cfg = driver::build_configuration(sess,
                                          repl.binary,
                                          wrapped);

    debug!("parsing");
    let mut crate = driver::parse_input(sess, cfg, wrapped);
    let mut opt = None;

    for crate.node.module.items.each |item| {
        match item.node {
            ast::item_fn(_, _, _, blk) => {
                if item.ident == sess.ident_of(~"main") {
                    opt = blk.node.expr;
                }
            }
            _ => {}
        }
    }

    let blk = match opt.get().node {
        ast::expr_call(_, exprs, _) => {
            match exprs[0].node {
                ast::expr_block(blk) => @blk,
                _ => fail
            }
        }
        _ => fail
    };

    debug!("configuration");
    crate = front::config::strip_unconfigured_items(crate);

    debug!("maybe building test harness");
    crate = front::test::modify_for_testing(sess, crate);

    debug!("expansion");
    crate = syntax::ext::expand::expand_crate(sess.parse_sess,
                                              sess.opts.cfg,
                                              crate);

    debug!("intrinsic injection");
    crate = front::intrinsic_inject::inject_intrinsic(sess, crate);

    debug!("core injection");
    crate = front::core_inject::maybe_inject_libcore_ref(sess, crate);

    debug!("building lint settings table");
    lint::build_settings_crate(sess, crate);

    debug!("ast indexing");
    let ast_map = syntax::ast_map::map_crate(sess.diagnostic(), *crate);

    debug!("external crate/lib resolution");
    creader::read_crates(sess.diagnostic(), *crate, sess.cstore,
                         sess.filesearch,
                         session::sess_os_to_meta_os(sess.targ_cfg.os),
                         sess.opts.static, sess.parse_sess.interner);

    debug!("language item collection");
    let lang_items = middle::lang_items::collect_language_items(crate, sess);

    debug!("resolution");
    let {def_map: def_map,
         exp_map2: exp_map2,
         trait_map: trait_map} = middle::resolve::resolve_crate(sess,
                                                                lang_items,
                                                                crate);

    debug!("freevar finding");
    let freevars = freevars::annotate_freevars(def_map, crate);

    debug!("region_resolution");
    let region_map = middle::region::resolve_crate(sess, def_map, crate);

    debug!("region paramaterization inference");
    let rp_set = middle::region::determine_rp_in_crate(sess, ast_map,
                                                       def_map, crate);

    debug!("typechecking");
    let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
                            region_map, rp_set, move lang_items, crate);
    let (method_map, vtable_map) = typeck::check_crate(ty_cx, trait_map,
                                                       crate);

    debug!("const marking");
    middle::const_eval::process_crate(crate, def_map, ty_cx);

    debug!("const checking");
    middle::check_const::check_crate(sess, crate, ast_map, def_map,
                                     method_map, ty_cx);

    debug!("privacy checking");
    middle::privacy::check_crate(ty_cx, &method_map, crate);

    debug!("loop checking");
    middle::check_loop::check_crate(ty_cx, crate);

    debug!("alt checking");
    middle::check_alt::check_crate(ty_cx, crate);

    debug!("liveness checking");
    let last_use_map = middle::liveness::check_crate(ty_cx,
                                                     method_map, crate);

    debug!("borrow checking");
    let (root_map, mutbl_map) = middle::borrowck::check_crate(ty_cx,
                                                              method_map,
                                                              last_use_map,
                                                              crate);

    debug!("kind checking");
    kind::check_crate(ty_cx, method_map, last_use_map, crate);

    debug!("lint checking");
    lint::check_crate(ty_cx, crate);

    let maps = {mutbl_map: mutbl_map,
                root_map: root_map,
                last_use_map: last_use_map,
                method_map: method_map,
                vtable_map: vtable_map};

    debug!("translation");
    let (llmod, _) = trans::base::trans_crate(sess, crate, ty_cx,
                                              ~path::from_str("<repl>"),
                                              exp_map2, maps);
    let pm = llvm::LLVMCreatePassManager();

    debug!("executing jit");
    back::link::jit::exec(sess, pm, llmod, 0, false);
    llvm::LLVMDisposePassManager(pm);

    debug!("recording input into repl history");
    record(repl, blk, sess.parse_sess.interner)
}

/// Run a command, e.g. :clear, :exit, etc.
fn run_cmd(repl: &mut Repl, _in: io::Reader, _out: io::Writer,
           cmd: ~str, _args: ~[~str]) {
    match cmd {
        ~"exit" => repl.running = false,
        ~"clear" => {
            repl.view_items = ~"";
            repl.stmts = ~"";

            // FIXME: Win32 version of linenoise doesn't have the required function
            //rl::clear();
        }
        ~"help" => {
            io::println(~":clear - clear the screen\n" +
                        ~":exit - exit from the repl\n" +
                        ~":help - show this message");
        }
        _ => io::println(~"unknown cmd: " + cmd)
    }
}

fn main() {
    let args = os::args();
    let in = io::stdin();
    let out = io::stdout();
    let mut repl = Repl {
        prompt: ~"rusti> ",
        binary: args[0],
        running: true,
        view_items: ~"",
        stmts: ~""
    };

    do rl::complete |line, suggest| {
        if line.starts_with(":") {
            suggest(~":clear");
            suggest(~":exit");
            suggest(~":help");
        }
    }

    while repl.running {
        let result = rl::read(repl.prompt);

        if result.is_none() {
            break;
        }

        let line = result.get();

        if line.is_empty() {
            io::println(~"()");

            loop;
        }

        rl::add_history(line);

        if line.starts_with(~":") {
            let full = line.substr(1, line.len() - 1);
            let split = full.split_char(' ');
            let len = split.len();

            if len > 0 {
                let cmd = split[0];

                if !cmd.is_empty() {
                    let args = if len > 1 {
                        do vec::view(split, 1, len - 1).map |arg| {
                            *arg
                        }
                    } else { ~[] };

                    run_cmd(&mut repl, in, out, cmd, args);

                    loop;
                }
            }
        }

        let result = do task::try |copy repl| {
            run(copy repl, line)
        };

        if result.is_ok() {
            repl = result.get();
        }
    }
}
<commit_msg>Long lines<commit_after>/**
 * A structure shared across REPL instances for storing history
 * such as statements and view items. I wish the AST was sendable.
 */
struct Repl {
    prompt: ~str,
    binary: ~str,
    running: bool,
    view_items: ~str,
    stmts: ~str
}

/// A utility function that hands off a pretty printer to a callback.
fn with_pp(intr: @token::ident_interner,
           cb: fn(pprust::ps, io::Writer)) -> ~str {
    do io::with_str_writer |writer| {
        let pp = pprust::rust_printer(writer, intr);

        cb(pp, writer);
        pp::eof(pp.s);
    }
}

/**
 * The AST (or the rest of rustc) are not sendable yet,
 * so recorded things are printed to strings. A terrible hack that
 * needs changes to rustc in order to be outed. This is unfortunately
 * going to cause the REPL to regress in parser performance,
 * because it has to parse the statements and view_items on each
 * input.
 */
fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl {
    let view_items = if blk.node.view_items.len() > 0 {
        let new_view_items = do with_pp(intr) |pp, writer| {
            for blk.node.view_items.each |view_item| {
                pprust::print_view_item(pp, *view_item);
                writer.write_line(~"");
            }
        };

        debug!("new view items %s", new_view_items);

        repl.view_items + "\n" + new_view_items
    } else { repl.view_items };
    let stmts = if blk.node.stmts.len() > 0 {
        let new_stmts = do with_pp(intr) |pp, writer| {
            for blk.node.stmts.each |stmt| {
                match stmt.node {
                    ast::stmt_decl(*) => {
                        pprust::print_stmt(pp, **stmt);
                        writer.write_line(~"");
                    }
                    ast::stmt_expr(expr, _) | ast::stmt_semi(expr, _) => {
                        match expr.node {
                            ast::expr_assign(*) |
                            ast::expr_assign_op(*) |
                            ast::expr_swap(*) => {
                                pprust::print_stmt(pp, **stmt);
                                writer.write_line(~"");
                            }
                            _ => {}
                        }
                    }
                }
            }
        };

        debug!("new stmts %s", new_stmts);

        repl.stmts + "\n" + new_stmts
    } else { repl.stmts };

    Repl{
        view_items: view_items,
        stmts: stmts,
        .. repl
    }
}

/// Run an input string in a Repl, returning the new Repl.
fn run(repl: Repl, input: ~str) -> Repl {
    let options: @session::options = @{
        crate_type: session::unknown_crate,
        binary: repl.binary,
        addl_lib_search_paths: ~[os::getcwd()],
        .. *session::basic_options()
    };

    debug!("building driver input");
    let head = include_str!("wrapper.rs");
    let foot = fmt!("%s\nfn main() {\n%s\n\nprint({\n%s\n})\n}",
                    repl.view_items, repl.stmts, input);
    let wrapped = driver::str_input(head + foot);

    debug!("inputting %s", head + foot);

    debug!("building a driver session");
    let sess = driver::build_session(options, diagnostic::emit);

    debug!("building driver configuration");
    let cfg = driver::build_configuration(sess,
                                          repl.binary,
                                          wrapped);

    debug!("parsing");
    let mut crate = driver::parse_input(sess, cfg, wrapped);
    let mut opt = None;

    for crate.node.module.items.each |item| {
        match item.node {
            ast::item_fn(_, _, _, blk) => {
                if item.ident == sess.ident_of(~"main") {
                    opt = blk.node.expr;
                }
            }
            _ => {}
        }
    }

    let blk = match opt.get().node {
        ast::expr_call(_, exprs, _) => {
            match exprs[0].node {
                ast::expr_block(blk) => @blk,
                _ => fail
            }
        }
        _ => fail
    };

    debug!("configuration");
    crate = front::config::strip_unconfigured_items(crate);

    debug!("maybe building test harness");
    crate = front::test::modify_for_testing(sess, crate);

    debug!("expansion");
    crate = syntax::ext::expand::expand_crate(sess.parse_sess,
                                              sess.opts.cfg,
                                              crate);

    debug!("intrinsic injection");
    crate = front::intrinsic_inject::inject_intrinsic(sess, crate);

    debug!("core injection");
    crate = front::core_inject::maybe_inject_libcore_ref(sess, crate);

    debug!("building lint settings table");
    lint::build_settings_crate(sess, crate);

    debug!("ast indexing");
    let ast_map = syntax::ast_map::map_crate(sess.diagnostic(), *crate);

    debug!("external crate/lib resolution");
    creader::read_crates(sess.diagnostic(), *crate, sess.cstore,
                         sess.filesearch,
                         session::sess_os_to_meta_os(sess.targ_cfg.os),
                         sess.opts.static, sess.parse_sess.interner);

    debug!("language item collection");
    let lang_items = middle::lang_items::collect_language_items(crate, sess);

    debug!("resolution");
    let {def_map: def_map,
         exp_map2: exp_map2,
         trait_map: trait_map} = middle::resolve::resolve_crate(sess,
                                                                lang_items,
                                                                crate);

    debug!("freevar finding");
    let freevars = freevars::annotate_freevars(def_map, crate);

    debug!("region_resolution");
    let region_map = middle::region::resolve_crate(sess, def_map, crate);

    debug!("region paramaterization inference");
    let rp_set = middle::region::determine_rp_in_crate(sess, ast_map,
                                                       def_map, crate);

    debug!("typechecking");
    let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
                            region_map, rp_set, move lang_items, crate);
    let (method_map, vtable_map) = typeck::check_crate(ty_cx, trait_map,
                                                       crate);

    debug!("const marking");
    middle::const_eval::process_crate(crate, def_map, ty_cx);

    debug!("const checking");
    middle::check_const::check_crate(sess, crate, ast_map, def_map,
                                     method_map, ty_cx);

    debug!("privacy checking");
    middle::privacy::check_crate(ty_cx, &method_map, crate);

    debug!("loop checking");
    middle::check_loop::check_crate(ty_cx, crate);

    debug!("alt checking");
    middle::check_alt::check_crate(ty_cx, crate);

    debug!("liveness checking");
    let last_use_map = middle::liveness::check_crate(ty_cx,
                                                     method_map, crate);

    debug!("borrow checking");
    let (root_map, mutbl_map) = middle::borrowck::check_crate(ty_cx,
                                                              method_map,
                                                              last_use_map,
                                                              crate);

    debug!("kind checking");
    kind::check_crate(ty_cx, method_map, last_use_map, crate);

    debug!("lint checking");
    lint::check_crate(ty_cx, crate);

    let maps = {mutbl_map: mutbl_map,
                root_map: root_map,
                last_use_map: last_use_map,
                method_map: method_map,
                vtable_map: vtable_map};

    debug!("translation");
    let (llmod, _) = trans::base::trans_crate(sess, crate, ty_cx,
                                              ~path::from_str("<repl>"),
                                              exp_map2, maps);
    let pm = llvm::LLVMCreatePassManager();

    debug!("executing jit");
    back::link::jit::exec(sess, pm, llmod, 0, false);
    llvm::LLVMDisposePassManager(pm);

    debug!("recording input into repl history");
    record(repl, blk, sess.parse_sess.interner)
}

/// Run a command, e.g. :clear, :exit, etc.
fn run_cmd(repl: &mut Repl, _in: io::Reader, _out: io::Writer,
           cmd: ~str, _args: ~[~str]) {
    match cmd {
        ~"exit" => repl.running = false,
        ~"clear" => {
            repl.view_items = ~"";
            repl.stmts = ~"";

            // XXX: Win32 version of linenoise can't do this
            //rl::clear();
        }
        ~"help" => {
            io::println(~":clear - clear the screen\n" +
                        ~":exit - exit from the repl\n" +
                        ~":help - show this message");
        }
        _ => io::println(~"unknown cmd: " + cmd)
    }
}

fn main() {
    let args = os::args();
    let in = io::stdin();
    let out = io::stdout();
    let mut repl = Repl {
        prompt: ~"rusti> ",
        binary: args[0],
        running: true,
        view_items: ~"",
        stmts: ~""
    };

    do rl::complete |line, suggest| {
        if line.starts_with(":") {
            suggest(~":clear");
            suggest(~":exit");
            suggest(~":help");
        }
    }

    while repl.running {
        let result = rl::read(repl.prompt);

        if result.is_none() {
            break;
        }

        let line = result.get();

        if line.is_empty() {
            io::println(~"()");

            loop;
        }

        rl::add_history(line);

        if line.starts_with(~":") {
            let full = line.substr(1, line.len() - 1);
            let split = full.split_char(' ');
            let len = split.len();

            if len > 0 {
                let cmd = split[0];

                if !cmd.is_empty() {
                    let args = if len > 1 {
                        do vec::view(split, 1, len - 1).map |arg| {
                            *arg
                        }
                    } else { ~[] };

                    run_cmd(&mut repl, in, out, cmd, args);

                    loop;
                }
            }
        }

        let result = do task::try |copy repl| {
            run(copy repl, line)
        };

        if result.is_ok() {
            repl = result.get();
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use common::BinarySerializable;
use super::Field;

#[derive(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub struct Term(Vec<u8>);

impl Term {

    fn type_num(&self,) -> u8 {
        self.0[0]
    }

    pub fn get_field(&self,) -> Field {
        Field(self.type_num())
    }

    pub fn from_field_u32(field: Field, val: u32) -> Term {
        let mut buffer = Vec::with_capacity(1 + 4);
        buffer.clear();
        field.serialize(&mut buffer).unwrap();
        val.serialize(&mut buffer).unwrap();
        Term(buffer)
    }

    pub fn from_field_text(field: Field, text: &str) -> Term {
        let mut buffer = Vec::with_capacity(1 + text.len());
        buffer.clear();
        field.serialize(&mut buffer).unwrap();
        buffer.extend(text.as_bytes());
        Term(buffer)
    }

    pub fn as_slice(&self,)->&[u8] {
        &self.0
    }
}

impl<'a> From<&'a [u8]> for Term {
    fn from(data: &[u8]) -> Term {
        Term(Vec::from(data))
    }
}

impl AsRef<[u8]> for Term {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl fmt::Debug for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Term({:?})", &self.0[..])
    }
}
<commit_msg>Added test for term<commit_after>use std::fmt;

use common::BinarySerializable;
use super::Field;

#[derive(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub struct Term(Vec<u8>);

impl Term {

    fn field_id(&self,) -> u8 {
        self.0[0]
    }

    pub fn get_field(&self,) -> Field {
        Field(self.field_id())
    }

    pub fn from_field_u32(field: Field, val: u32) -> Term {
        let mut buffer = Vec::with_capacity(1 + 4);
        buffer.clear();
        field.serialize(&mut buffer).unwrap();
        val.serialize(&mut buffer).unwrap();
        Term(buffer)
    }

    pub fn from_field_text(field: Field, text: &str) -> Term {
        let mut buffer = Vec::with_capacity(1 + text.len());
        buffer.clear();
        field.serialize(&mut buffer).unwrap();
        buffer.extend(text.as_bytes());
        Term(buffer)
    }

    pub fn as_slice(&self,)->&[u8] {
        &self.0
    }
}

impl<'a> From<&'a [u8]> for Term {
    fn from(data: &[u8]) -> Term {
        Term(Vec::from(data))
    }
}

impl AsRef<[u8]> for Term {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl fmt::Debug for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Term({:?})", &self.0[..])
    }
}

#[cfg(test)]
mod tests {

    use schema::*;

    #[test]
    pub fn test_term() {
        let mut schema = Schema::new();
        let _ = schema.add_text_field("text", STRING);
        let title_field = schema.add_text_field("title", STRING);
        let count_field = schema.add_text_field("count", STRING);
        {
            let term = Term::from_field_text(title_field, "test");
            assert_eq!(term.get_field(), title_field);
            assert_eq!(term.as_slice()[0], 1u8);
            assert_eq!(&term.as_slice()[1..], "test".as_bytes());
        }
        {
            let term = Term::from_field_u32(count_field, 983u32);
            assert_eq!(term.get_field(), count_field);
            assert_eq!(term.as_slice()[0], 2u8);
            assert_eq!(term.as_slice().len(), 5);
            assert_eq!(term.as_slice()[1], (983u32 % 256u32) as u8);
        }

    }
}<|endoftext|>


<commit_before>//! Module `tcp` provides support for channels that communicate
//! over TCP.

use serialize::{Decodable, Encodable};
use serialize::json::{Decoder, DecoderError, decode, Encoder};
use std::io::{IoError, IoErrorKind, IoResult, TcpStream};
use std::io::net::ip::ToSocketAddr;
use std::io::net::tcp::TcpAcceptor;
use std::sync::{Arc, Mutex};
use super::ReceiverError;

/// `TcpSender` is the sender half of a TCP connection.
pub struct TcpSender<T>(Arc<Mutex<TcpStream>>);

impl<T> TcpSender<T> {
    /// Create a new TcpSender (aka TCP client) for the specified address. It will
    /// fail if no TcpReceiver (aka TCP server) is waiting to receive the connection.
    pub fn new<A: ToSocketAddr>(addr: A) -> IoResult<TcpSender<T>> {
        Ok(TcpSender(Arc::new(Mutex::new(try!(TcpStream::connect(addr))))))
    }
}

impl<T> super::Sender<T> for TcpSender<T> where T: Encodable<Encoder<'static>, IoError> + Send {
    /// Non-blocking send along the channel.
    #[allow(unused_must_use)]
    fn send(&mut self, t: T) {
        let stream = self.0.clone();
        spawn(proc() {
            let e = Encoder::buffer_encode(&t);
            let mut stream = stream.lock();
            stream.write_le_uint(e.len());
            stream.write(e.as_slice());
            stream.flush();
        });
    }
}

/// TcpReceiver is the receiver half of a TCP connection.
pub struct TcpReceiver<T> {
    streams: Arc<Mutex<Vec<TcpStream>>>,
    acceptor: TcpAcceptor,
    closed: bool,
}

impl<T> TcpReceiver<T> {
    /// Create a new TcpReceiver (aka TCP server) bound to the specified address.
    #[allow(unused_must_use)]
    pub fn new<A: ToSocketAddr>(addr: A) -> IoResult<TcpReceiver<T>> {
        use std::io::{Acceptor, Listener};
        use std::io::net::tcp::TcpListener;

        let streams = Arc::new(Mutex::new(Vec::new()));

        let listener = try!(TcpListener::bind(addr));
        let acceptor = try!(listener.listen());
        {
            let streams = streams.clone();
            let mut acceptor = acceptor.clone();
            spawn(proc() {
                for stream in acceptor.incoming() {
                    let mut streams = streams.lock();
                    match stream {
                        Ok(stream) => streams.push(stream),
                        Err(ref e) if e.kind == IoErrorKind::EndOfFile => return,
                        Err(e) => panic!("{}", e),
                    }
                }
            });
        }

        Ok(TcpReceiver{ streams: streams, acceptor: acceptor, closed: false })
    }
}

impl<T> super::Receiver<T> for TcpReceiver<T> where T: Decodable<Decoder, DecoderError> {
    /// Attempt to receive a value on the channel. This method blocks until a value
    /// is available.
    fn try_recv(&mut self) -> Result<T, ReceiverError> {
        use std::task;
        let mut finished = Vec::new();
        loop {
            {
                if self.closed {
                    return Err(ReceiverError::EndOfFile);
                }
                let mut streams = self.streams.lock();
                let mut found = None;
                for (i, stream) in streams.iter_mut().enumerate() {
                    stream.set_read_timeout(Some(10)); // TODO: set this value as a config?
                    let size = match stream.read_le_uint() {
                        Ok(size) => size,
                        Err(ref e) if e.kind == IoErrorKind::TimedOut => continue,
                        Err(ref e) if e.kind == IoErrorKind::EndOfFile => { finished.push(i); continue },
                        Err(e) => return Err(ReceiverError::IoError(e)),
                    };
                    let data = try!(stream.read_exact(size));
                    let string = try!(String::from_utf8(data));
                    let decoded = try!(decode::<T>(string.as_slice()));
                    found = Some(decoded);
                    break;
                }
                if finished.len() > 0 {
                    let mut offset = 0u;
                    for i in finished.iter() {
                        streams.remove(*i - offset);
                        offset += 1;
                    }
                    finished.clear();
                }
                if let Some(decoded) = found {
                    return Ok(decoded);
                }
            }
            task::deschedule();
        }
    }
}

#[unsafe_destructor]
impl<T> Drop for TcpReceiver<T> {
    #[allow(unused_must_use)]
    fn drop(&mut self) {
        self.acceptor.close_accept();
        self.closed = true;
    }
}

#[cfg(test)]
mod test {
    use super::super::{Sender, Receiver};
    use super::{TcpSender, TcpReceiver};

    #[deriving(Encodable, Decodable)]
    enum MyEnum {
        NoValue,
        IntValue(int),
    }

    #[test]
    fn send_and_recv_string() {
        const ADDR: &'static str = "127.0.0.1:8080";
        let mut receiver: TcpReceiver<String> = TcpReceiver::new(ADDR).unwrap();
        let mut sender: TcpSender<String> = TcpSender::new(ADDR).unwrap();

        sender.send("hello superchan!".into_string());
        assert_eq!("hello superchan!".into_string(), receiver.recv());
    }

    #[test]
    fn send_and_recv_int() {
        const ADDR: &'static str = "127.0.0.1:8081";
        let mut receiver: TcpReceiver<int> = TcpReceiver::new(ADDR).unwrap();
        let mut sender: TcpSender<int> = TcpSender::new(ADDR).unwrap();

        sender.send(-13);
        assert_eq!(-13, receiver.recv());
    }

    #[test]
    fn send_and_recv_custom() {
        const ADDR: &'static str = "127.0.0.1:8082";
        let mut receiver: TcpReceiver<MyEnum> = TcpReceiver::new(ADDR).unwrap();
        let mut sender: TcpSender<MyEnum> = TcpSender::new(ADDR).unwrap();

        sender.send(MyEnum::IntValue(3));
        match receiver.recv() {
            MyEnum::IntValue(val) => assert_eq!(val, 3),
            _ => panic!("received unexpected MyEnum value"),
        }
    }

    #[test]
    fn multi_send() {
        const ADDR: &'static str = "127.0.0.1:8083";
        let mut receiver: TcpReceiver<int> = TcpReceiver::new(ADDR).unwrap();
        let mut sender1: TcpSender<int> = TcpSender::new(ADDR).unwrap();
        let mut sender2: TcpSender<int> = TcpSender::new(ADDR).unwrap();

        sender1.send(1);
        sender2.send(2);
        let (val1, val2) = (receiver.recv(), receiver.recv());
        assert!((val1 == 1 && val2 == 2) || (val1 == 2 && val2 == 1));
    }
}
<commit_msg>Refactor so a thread isn't spawned for each sent message.<commit_after>//! Module `tcp` provides support for channels that communicate
//! over TCP.

use serialize::{Decodable, Encodable};
use serialize::json::{Decoder, DecoderError, decode, Encoder};
use std::io::{IoError, IoErrorKind, IoResult, TcpStream};
use std::io::net::ip::ToSocketAddr;
use std::io::net::tcp::TcpAcceptor;
use std::sync::{Arc, Mutex};
use super::ReceiverError;

/// `TcpSender` is the sender half of a TCP connection.
pub struct TcpSender<T>(Sender<T>);

impl<T> TcpSender<T> where T: Encodable<Encoder<'static>, IoError> + Send {
    /// Create a new TcpSender (aka TCP client) for the specified address. It will
    /// fail if no TcpReceiver (aka TCP server) is waiting to receive the connection.
    #[allow(unused_must_use)]
    pub fn new<A: ToSocketAddr>(addr: A) -> IoResult<TcpSender<T>> {
        let (tx, rx) = channel();
        let mut stream = try!(TcpStream::connect(addr));
        spawn(proc() {
            for t in rx.iter() {
                let e = Encoder::buffer_encode(&t);
                stream.write_le_uint(e.len());
                stream.write(e.as_slice());
                stream.flush();
            }
        });
        Ok(TcpSender(tx))
    }
}

impl<T> super::Sender<T> for TcpSender<T> where T: Encodable<Encoder<'static>, IoError> + Send {
    /// Non-blocking send along the channel.
    fn send(&mut self, t: T) {
        self.0.send(t);
    }
}

/// TcpReceiver is the receiver half of a TCP connection.
pub struct TcpReceiver<T> {
    streams: Arc<Mutex<Vec<TcpStream>>>,
    acceptor: TcpAcceptor,
    closed: bool,
}

impl<T> TcpReceiver<T> {
    /// Create a new TcpReceiver (aka TCP server) bound to the specified address.
    #[allow(unused_must_use)]
    pub fn new<A: ToSocketAddr>(addr: A) -> IoResult<TcpReceiver<T>> {
        use std::io::{Acceptor, Listener};
        use std::io::net::tcp::TcpListener;

        let streams = Arc::new(Mutex::new(Vec::new()));

        let listener = try!(TcpListener::bind(addr));
        let acceptor = try!(listener.listen());
        {
            let streams = streams.clone();
            let mut acceptor = acceptor.clone();
            spawn(proc() {
                for stream in acceptor.incoming() {
                    let mut streams = streams.lock();
                    match stream {
                        Ok(stream) => streams.push(stream),
                        Err(ref e) if e.kind == IoErrorKind::EndOfFile => return,
                        Err(e) => panic!("{}", e),
                    }
                }
            });
        }

        Ok(TcpReceiver{ streams: streams, acceptor: acceptor, closed: false })
    }
}

impl<T> super::Receiver<T> for TcpReceiver<T> where T: Decodable<Decoder, DecoderError> {
    /// Attempt to receive a value on the channel. This method blocks until a value
    /// is available.
    fn try_recv(&mut self) -> Result<T, ReceiverError> {
        use std::task;
        let mut finished = Vec::new();
        loop {
            {
                if self.closed {
                    return Err(ReceiverError::EndOfFile);
                }
                let mut streams = self.streams.lock();
                let mut found = None;
                for (i, stream) in streams.iter_mut().enumerate() {
                    stream.set_read_timeout(Some(10)); // TODO: set this value as a config?
                    let size = match stream.read_le_uint() {
                        Ok(size) => size,
                        Err(ref e) if e.kind == IoErrorKind::TimedOut => continue,
                        Err(ref e) if e.kind == IoErrorKind::EndOfFile => { finished.push(i); continue },
                        Err(e) => return Err(ReceiverError::IoError(e)),
                    };
                    let data = try!(stream.read_exact(size));
                    let string = try!(String::from_utf8(data));
                    let decoded = try!(decode::<T>(string.as_slice()));
                    found = Some(decoded);
                    break;
                }
                if finished.len() > 0 {
                    let mut offset = 0u;
                    for i in finished.iter() {
                        streams.remove(*i - offset);
                        offset += 1;
                    }
                    finished.clear();
                }
                if let Some(decoded) = found {
                    return Ok(decoded);
                }
            }
            task::deschedule();
        }
    }
}

#[unsafe_destructor]
impl<T> Drop for TcpReceiver<T> {
    #[allow(unused_must_use)]
    fn drop(&mut self) {
        self.acceptor.close_accept();
        self.closed = true;
    }
}

#[cfg(test)]
mod test {
    use super::super::{Sender, Receiver};
    use super::{TcpSender, TcpReceiver};

    #[deriving(Encodable, Decodable)]
    enum MyEnum {
        NoValue,
        IntValue(int),
    }

    #[test]
    fn send_and_recv_string() {
        const ADDR: &'static str = "127.0.0.1:8080";
        let mut receiver: TcpReceiver<String> = TcpReceiver::new(ADDR).unwrap();
        let mut sender: TcpSender<String> = TcpSender::new(ADDR).unwrap();

        sender.send("hello superchan!".into_string());
        assert_eq!("hello superchan!".into_string(), receiver.recv());
    }

    #[test]
    fn send_and_recv_int() {
        const ADDR: &'static str = "127.0.0.1:8081";
        let mut receiver: TcpReceiver<int> = TcpReceiver::new(ADDR).unwrap();
        let mut sender: TcpSender<int> = TcpSender::new(ADDR).unwrap();

        sender.send(-13);
        assert_eq!(-13, receiver.recv());
    }

    #[test]
    fn send_and_recv_custom() {
        const ADDR: &'static str = "127.0.0.1:8082";
        let mut receiver: TcpReceiver<MyEnum> = TcpReceiver::new(ADDR).unwrap();
        let mut sender: TcpSender<MyEnum> = TcpSender::new(ADDR).unwrap();

        sender.send(MyEnum::IntValue(3));
        match receiver.recv() {
            MyEnum::IntValue(val) => assert_eq!(val, 3),
            _ => panic!("received unexpected MyEnum value"),
        }
    }

    #[test]
    fn multi_send() {
        const ADDR: &'static str = "127.0.0.1:8083";
        let mut receiver: TcpReceiver<int> = TcpReceiver::new(ADDR).unwrap();
        let mut sender1: TcpSender<int> = TcpSender::new(ADDR).unwrap();
        let mut sender2: TcpSender<int> = TcpSender::new(ADDR).unwrap();

        sender1.send(1);
        sender2.send(2);
        let (val1, val2) = (receiver.recv(), receiver.recv());
        assert!((val1 == 1 && val2 == 2) || (val1 == 2 && val2 == 1));
    }
}
<|endoftext|>


<commit_before>//! Treiber stacks.

use std::sync::atomic;
use std::ptr;
use {Atomic, Guard};

/// A Treiber stack.
///
/// Treiber stacks are one way to implement concurrent LIFO stack.
///
/// Treiber stacks builds on linked lists. They are lock-free and non-blocking. It can be compared
/// to transactional memory in that it repeats operations, if another thread changes it while.
///
/// The ABA problem is of course addressed through the API of this crate.
pub struct Treiber<T> {
    /// The head node.
    head: Atomic<Node<T>>,
}

impl<T> Treiber<T> {
    /// Create a new, empty Treiber stack.
    pub fn new() -> Treiber<T> {
        Treiber {
            head: Atomic::default(),
        }
    }

    /// Pop an item from the stack.
    // TODO: Change this return type.
    pub fn pop(&self) -> Option<Guard<T>> {
        // TODO: Use `catch {}` here when it lands.
        // Read the head snapshot.
        let mut snapshot = self.head.load(atomic::Ordering::Acquire);

        // Unless the head snapshot is `None`, try to replace it with the tail.
        while let Some(node) = snapshot {
            // Attempt to replace the head with the tail of the head.
            match unsafe {
                self.head.compare_and_swap_raw(
                    &*node,
                    node.next as *mut Node<T>,
                    atomic::Ordering::Release,
                )
            } {
                // It succeeded; return the item.
                Ok(_) => return Some(node.map(|x| &x.item)),
                // It failed, update the head snapshot and continue.
                Err(new) => snapshot = new,
            }
        }

        // As the head was empty, there is nothing to pop.
        None
    }

    /// Push an item to the stack.
    pub fn push(&self, item: T)
    where T: 'static {
        // Load the head snapshot.
        let mut snapshot = self.head.load(atomic::Ordering::Acquire);
        let mut snapshot_ptr: Option<*const Node<T>>;

        // TODO: Use `catch {}` here when it lands.
        // Construct a node, which will be the new head.
        let mut node = Box::new(Node {
            item: item,
            // Placeholder; we will replace it with an actual value in the loop.
            next: ptr::null(),
        });

        loop {
            // Derive the nullable snapshot pointer from the head snapshot.
            snapshot_ptr = snapshot.as_ref().map(Guard::as_raw);
            // Construct the next-pointer of the new node from the head snapshot.
            node.next = snapshot_ptr.unwrap_or(ptr::null());

            // TODO: This should be something that ignores the guard creation when the CAS
            //       succeeds, because it's expensive to do and not used anyway. It should be easy
            //       enough to implement, but I am struggling to come up with a good name for the
            //       method.

            // CAS from the read pointer to the new head.
            match self.head.compare_and_swap(snapshot_ptr, Some(node), atomic::Ordering::Release) {
                // If it succeeds, the item has been pushed.
                Ok(_) => break,
                // If it fails, we will retry the CAS with updated values.
                Err((new_head, Some(node2))) => {
                    // Update the head snapshot.
                    snapshot = new_head;
                    // Put the box we gave back to the variable where it belongs.
                    node = node2;
                },
                // This should never be reached as we gave an argument which was unconditionally
                // `Some`.
                _ => unreachable!(),
            }
        }
    }
}

/// A node in the stack.
struct Node<T> {
    /// The data this node holds.
    item: T,
    /// The next node.
    next: *const Node<T>,
}

impl<T> Drop for Node<T> {
    fn drop(&mut self) {
        // FIXME: Since this is recursive (and although it is likely optimized out), there might be
        //        cases where this leads to stack overflow, given correct compilation flags and
        //        sufficiently many elements.

        // Recursively drop the next node, if it exists.
        if !self.next.is_null() {
            unsafe {
                drop(Box::from_raw(self.next as *mut Node<T>));
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::thread;
    use std::sync::Arc;
    use std::sync::atomic::AtomicUsize;

    #[derive(Clone)]
    struct Dropper {
        d: Arc<AtomicUsize>,
    }

    impl Drop for Dropper {
        fn drop(&mut self) {
            self.d.fetch_add(1, atomic::Ordering::Relaxed);
        }
    }

    #[test]
    fn simple1() {
        let stack = Treiber::new();

        stack.push(1);
        stack.push(200);
        stack.push(44);

        assert_eq!(*stack.pop().unwrap(), 44);
        assert_eq!(*stack.pop().unwrap(), 200);
        assert_eq!(*stack.pop().unwrap(), 1);
        assert!(stack.pop().is_none());

        ::gc();
    }

    #[test]
    fn simple2() {
        let stack = Treiber::new();

        for _ in 0..16 {
            stack.push(1);
            stack.push(200);
            stack.push(44);

            assert_eq!(*stack.pop().unwrap(), 44);
            assert_eq!(*stack.pop().unwrap(), 200);
            stack.push(20000);

            assert_eq!(*stack.pop().unwrap(), 20000);
            assert_eq!(*stack.pop().unwrap(), 1);

            assert!(stack.pop().is_none());
            assert!(stack.pop().is_none());
            assert!(stack.pop().is_none());
            assert!(stack.pop().is_none());
        }

        ::gc();
    }

    #[test]
    fn simple3() {
        let stack = Treiber::new();

        for i in 0..10000 {
            stack.push(i);
        }

        for i in (0..10000).rev() {
            assert_eq!(*stack.pop().unwrap(), i);
        }

        for i in 0..10000 {
            stack.push(i);
        }

        for i in (0..10000).rev() {
            assert_eq!(*stack.pop().unwrap(), i);
        }

        assert!(stack.pop().is_none());
        assert!(stack.pop().is_none());
        assert!(stack.pop().is_none());
        assert!(stack.pop().is_none());
    }

    #[test]
    fn push_pop() {
        let stack = Arc::new(Treiber::new());
        let mut j = Vec::new();
        for _ in 0..16 {
            let s = stack.clone();
            j.push(thread::spawn(move || {
                for _ in 0..10_000_000 {
                    s.push(23);
                    assert_eq!(*s.pop().unwrap(), 23);
                }
            }));
        }

        for i in j {
            i.join().unwrap();
        }
    }

    #[test]
    fn increment() {
        let stack = Arc::new(Treiber::<u64>::new());
        let mut j = Vec::new();

        // 16 times, we add the numbers from 0 to 1000 to the only element in the stack.
        for _ in 0..16 {
            let s = stack.clone();
            j.push(thread::spawn(move || {
                for n in 0..1000 {
                    loop {
                        if let Some(x) = s.pop() {
                            s.push(*x + n);
                            break;
                        }
                    }
                }
            }));
        }

        for i in j {
            i.join().unwrap();
        }

        assert!(*stack.pop().unwrap() == 16 * 1000 * 1001 / 2);
    }

    #[test]
    fn sum() {
        let stack = Arc::new(Treiber::<i64>::new());
        let mut j = Vec::new();

        for _ in 0..1000 {
            stack.push(10);
        }

        // We preserve the sum of the stack's elements.
        for _ in 0..16 {
            let s = stack.clone();
            j.push(thread::spawn(move || {
                for _ in 0..100000 {
                    loop {
                        if let Some(a) = s.pop() {
                            loop {
                                if let Some(b) = s.pop() {
                                    s.push(*a + 1);
                                    s.push(*b - 1);

                                    break;
                                }
                            }

                            break;
                        }
                    }
                }
            }));
        }

        for i in j {
            i.join().unwrap();
        }

        let mut sum = 0;
        while let Some(x) = stack.pop() {
            sum += *x;
        }
        assert_eq!(sum, 10000);
    }

    #[test]
    fn drop() {
        let drops = Arc::new(AtomicUsize::default());
        let stack = Arc::new(Treiber::new());

        let d = Dropper {
            d: drops.clone(),
        };

        let mut j = Vec::new();
        for _ in 0..16 {
            let d = d.clone();
            let stack = stack.clone();

            j.push(thread::spawn(move || {
                for _ in 0..20 {
                    stack.push(d.clone());
                }

                stack.pop();
                stack.pop();
            }))
        }

        for i in j {
            i.join().unwrap();
        }

        ::gc();
        // The 16 are for the `d` variable in the loop above.
        assert_eq!(drops.load(atomic::Ordering::Relaxed), 32 + 16);

        // Drop the last arc.
        let _ = stack;
        ::gc();

        assert_eq!(drops.load(atomic::Ordering::Relaxed), 200 + 16);
    }
}
<commit_msg>Fix the `conc::sync::treiber::tests::increment` test, which previously looped infinitely.<commit_after>//! Treiber stacks.

use std::sync::atomic;
use std::ptr;
use {Atomic, Guard};

/// A Treiber stack.
///
/// Treiber stacks are one way to implement concurrent LIFO stack.
///
/// Treiber stacks builds on linked lists. They are lock-free and non-blocking. It can be compared
/// to transactional memory in that it repeats operations, if another thread changes it while.
///
/// The ABA problem is of course addressed through the API of this crate.
pub struct Treiber<T> {
    /// The head node.
    head: Atomic<Node<T>>,
}

impl<T> Treiber<T> {
    /// Create a new, empty Treiber stack.
    pub fn new() -> Treiber<T> {
        Treiber {
            head: Atomic::default(),
        }
    }

    /// Pop an item from the stack.
    // TODO: Change this return type.
    pub fn pop(&self) -> Option<Guard<T>> {
        // TODO: Use `catch {}` here when it lands.
        // Read the head snapshot.
        let mut snapshot = self.head.load(atomic::Ordering::Acquire);

        // Unless the head snapshot is `None`, try to replace it with the tail.
        while let Some(node) = snapshot {
            // Attempt to replace the head with the tail of the head.
            match unsafe {
                self.head.compare_and_swap_raw(
                    node.as_raw(),
                    node.next as *mut Node<T>,
                    atomic::Ordering::Release,
                )
            } {
                // It succeeded; return the item.
                Ok(_) => return Some(node.map(|x| &x.item)),
                // It failed, update the head snapshot and continue.
                Err(new) => snapshot = new,
            }
        }

        // As the head was empty, there is nothing to pop.
        None
    }

    /// Push an item to the stack.
    pub fn push(&self, item: T)
    where T: 'static {
        // Load the head snapshot.
        let mut snapshot = self.head.load(atomic::Ordering::Relaxed);
        let mut snapshot_ptr: Option<*const Node<T>>;

        // TODO: Use `catch {}` here when it lands.
        // Construct a node, which will be the new head.
        let mut node = Box::new(Node {
            item: item,
            // Placeholder; we will replace it with an actual value in the loop.
            next: ptr::null(),
        });

        loop {
            // Derive the nullable snapshot pointer from the head snapshot.
            snapshot_ptr = snapshot.as_ref().map(Guard::as_raw);
            // Construct the next-pointer of the new node from the head snapshot.
            node.next = snapshot_ptr.unwrap_or(ptr::null());

            // TODO: This should be something that ignores the guard creation when the CAS
            //       succeeds, because it's expensive to do and not used anyway. It should be easy
            //       enough to implement, but I am struggling to come up with a good name for the
            //       method.

            // CAS from the read pointer to the new head.
            match self.head.compare_and_swap(snapshot_ptr, Some(node), atomic::Ordering::Release) {
                // If it succeeds, the item has been pushed.
                Ok(_) => break,
                // If it fails, we will retry the CAS with updated values.
                Err((new_head, Some(node2))) => {
                    // Update the head snapshot.
                    snapshot = new_head;
                    // Put the box we gave back to the variable where it belongs.
                    node = node2;
                },
                // This should never be reached as we gave an argument which was unconditionally
                // `Some`.
                _ => unreachable!(),
            }
        }
    }
}

/// A node in the stack.
struct Node<T> {
    /// The data this node holds.
    item: T,
    /// The next node.
    next: *const Node<T>,
}

impl<T> Drop for Node<T> {
    fn drop(&mut self) {
        // FIXME: Since this is recursive (and although it is likely optimized out), there might be
        //        cases where this leads to stack overflow, given correct compilation flags and
        //        sufficiently many elements.

        // Recursively drop the next node, if it exists.
        if !self.next.is_null() {
            unsafe {
                drop(Box::from_raw(self.next as *mut Node<T>));
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::thread;
    use std::sync::Arc;
    use std::sync::atomic::AtomicUsize;

    #[derive(Clone)]
    struct Dropper {
        d: Arc<AtomicUsize>,
    }

    impl Drop for Dropper {
        fn drop(&mut self) {
            self.d.fetch_add(1, atomic::Ordering::Relaxed);
        }
    }

    #[test]
    fn simple1() {
        let stack = Treiber::new();

        stack.push(1);
        stack.push(200);
        stack.push(44);

        assert_eq!(*stack.pop().unwrap(), 44);
        assert_eq!(*stack.pop().unwrap(), 200);
        assert_eq!(*stack.pop().unwrap(), 1);
        assert!(stack.pop().is_none());

        ::gc();
    }

    #[test]
    fn simple2() {
        let stack = Treiber::new();

        for _ in 0..16 {
            stack.push(1);
            stack.push(200);
            stack.push(44);

            assert_eq!(*stack.pop().unwrap(), 44);
            assert_eq!(*stack.pop().unwrap(), 200);
            stack.push(20000);

            assert_eq!(*stack.pop().unwrap(), 20000);
            assert_eq!(*stack.pop().unwrap(), 1);

            assert!(stack.pop().is_none());
            assert!(stack.pop().is_none());
            assert!(stack.pop().is_none());
            assert!(stack.pop().is_none());
        }

        ::gc();
    }

    #[test]
    fn simple3() {
        let stack = Treiber::new();

        for i in 0..10000 {
            stack.push(i);
        }

        for i in (0..10000).rev() {
            assert_eq!(*stack.pop().unwrap(), i);
        }

        for i in 0..10000 {
            stack.push(i);
        }

        for i in (0..10000).rev() {
            assert_eq!(*stack.pop().unwrap(), i);
        }

        assert!(stack.pop().is_none());
        assert!(stack.pop().is_none());
        assert!(stack.pop().is_none());
        assert!(stack.pop().is_none());
    }

    #[test]
    fn push_pop() {
        let stack = Arc::new(Treiber::new());
        let mut j = Vec::new();
        for _ in 0..16 {
            let s = stack.clone();
            j.push(thread::spawn(move || {
                for _ in 0..10_000_000 {
                    s.push(23);
                    assert_eq!(*s.pop().unwrap(), 23);
                }
            }));
        }

        for i in j {
            i.join().unwrap();
        }
    }

    #[test]
    fn increment() {
        let stack = Arc::new(Treiber::<u64>::new());
        stack.push(0);
        let mut j = Vec::new();

        // 16 times, we add the numbers from 0 to 1000 to the only element in the stack.
        for _ in 0..16 {
            let s = stack.clone();
            j.push(thread::spawn(move || {
                for n in 0..1001 {
                    loop {
                        if let Some(x) = s.pop() {
                            s.push(*x + n);
                            break;
                        }
                    }
                }
            }));
        }

        for i in j {
            i.join().unwrap();
        }

        assert_eq!(*stack.pop().unwrap(), 16 * 1000 * 1001 / 2);
    }

    #[test]
    fn sum() {
        let stack = Arc::new(Treiber::<i64>::new());
        let mut j = Vec::new();

        for _ in 0..1000 {
            stack.push(10);
        }

        // We preserve the sum of the stack's elements.
        for _ in 0..16 {
            let s = stack.clone();
            j.push(thread::spawn(move || {
                for _ in 0..100000 {
                    loop {
                        if let Some(a) = s.pop() {
                            loop {
                                if let Some(b) = s.pop() {
                                    s.push(*a + 1);
                                    s.push(*b - 1);

                                    break;
                                }
                            }

                            break;
                        }
                    }
                }
            }));
        }

        for i in j {
            i.join().unwrap();
        }

        let mut sum = 0;
        while let Some(x) = stack.pop() {
            sum += *x;
        }
        assert_eq!(sum, 10000);
    }

    #[test]
    fn drop() {
        let drops = Arc::new(AtomicUsize::default());
        let stack = Arc::new(Treiber::new());

        let d = Dropper {
            d: drops.clone(),
        };

        let mut j = Vec::new();
        for _ in 0..16 {
            let d = d.clone();
            let stack = stack.clone();

            j.push(thread::spawn(move || {
                for _ in 0..20 {
                    stack.push(d.clone());
                }

                stack.pop();
                stack.pop();
            }))
        }

        for i in j {
            i.join().unwrap();
        }

        ::gc();
        // The 16 are for the `d` variable in the loop above.
        assert_eq!(drops.load(atomic::Ordering::Relaxed), 32 + 16);

        // Drop the last arc.
        let _ = stack;
        ::gc();

        assert_eq!(drops.load(atomic::Ordering::Relaxed), 200 + 16);
    }
}
<|endoftext|>


<commit_before>#[derive(Default)]
pub struct Cpu {
    // Program counter.
    pub pc: u16,

    // The stack.
    stack: [u16; 12],

    // Stack pointer.
    sp: u8,

    // General purpose registers v0-vf.
    v0: u8,
    v1: u8,
    v2: u8,
    v3: u8,
    v4: u8,
    v5: u8,
    v6: u8,
    v7: u8,
    v8: u8,
    v9: u8,
    va: u8,
    vb: u8,
    vc: u8,
    vd: u8,
    ve: u8,
    vf: u8,

    // Address register "I".
    i: u16,

    // Timer and sound registers.
    dt: u8,
    st: u8,
}

impl Cpu {
    pub fn new() -> Cpu {
        Cpu::default()
    }

    #[inline(always)]
    pub fn execute_instruction(&mut self, instr: u16) {
        let opcode = (instr >> 12) as u8;

        match opcode {
            0x6 => {
                let reg = ((instr << 4) >> 12) as u8;
                let byte = ((instr << 8) >> 8) as u8;

                println!("regval: {:#x}", self.va);
                self.set_reg(reg, byte);

                //println!("reg: {:#x}", reg);
                //println!("byte: {:#x}", byte);
            },
            _ => {
                panic!("Found unknown opcode at addr: {:#x}", instr);
            }
        }

        //println!("opcode: {:#x}", opcode);
        //println!("addr: {:#x}", instr);
    }

    fn set_reg(&mut self, reg: u8, byte: u8) {
        match reg {
            0x0 => self.v0 = byte,
            0x1 => self.v1 = byte,
            0x2 => self.v2 = byte,
            0x3 => self.v3 = byte,
            0x4 => self.v4 = byte,
            0x5 => self.v5 = byte,
            0x6 => self.v6 = byte,
            0x7 => self.v7 = byte,
            0x8 => self.v8 = byte,
            0x9 => self.v9 = byte,
            0xa => self.va = byte,
            0xb => self.vb = byte,
            0xc => self.vc = byte,
            0xd => self.vd = byte,
            0xe => self.ve = byte,
            0xf => self.vf = byte,
            _ => {
                panic!("Cannot set unknown register: V{:X}", reg);
            }
        }
    }
}
<commit_msg>Program counter now increments<commit_after>const INSTRUCTION_SIZE: u16 = 2;

#[derive(Default, Debug)]
pub struct Cpu {
    // Program counter.
    pub pc: u16,

    // The stack.
    stack: [u16; 12],

    // Stack pointer.
    sp: u8,

    // General purpose registers v0-vf.
    v0: u8,
    v1: u8,
    v2: u8,
    v3: u8,
    v4: u8,
    v5: u8,
    v6: u8,
    v7: u8,
    v8: u8,
    v9: u8,
    va: u8,
    vb: u8,
    vc: u8,
    vd: u8,
    ve: u8,
    vf: u8,

    // Address register "I".
    i: u16,

    // Timer and sound registers.
    dt: u8,
    st: u8,
}

impl Cpu {
    pub fn new() -> Cpu {
        Cpu::default()
    }

    #[inline(always)]
    pub fn execute_instruction(&mut self, instr: u16) {
        let opcode = (instr >> 12) as u8;

        match opcode {
            0x6 => {
                let reg = ((instr << 4) >> 12) as u8;
                let byte = ((instr << 8) >> 8) as u8;
                self.set_reg(reg, byte);
            },
            _ => {
                println!("cpu: {:#?}", self);
                panic!("Found unknown opcode at addr: {:#x}", instr);
            }
        }

        self.pc += INSTRUCTION_SIZE;

        println!("addr: {:#x}", instr);
    }

    /// Sets the value of a general purpose register.
    fn set_reg(&mut self, reg: u8, byte: u8) {
        match reg {
            0x0 => self.v0 = byte,
            0x1 => self.v1 = byte,
            0x2 => self.v2 = byte,
            0x3 => self.v3 = byte,
            0x4 => self.v4 = byte,
            0x5 => self.v5 = byte,
            0x6 => self.v6 = byte,
            0x7 => self.v7 = byte,
            0x8 => self.v8 = byte,
            0x9 => self.v9 = byte,
            0xa => self.va = byte,
            0xb => self.vb = byte,
            0xc => self.vc = byte,
            0xd => self.vd = byte,
            0xe => self.ve = byte,
            0xf => self.vf = byte,
            _ => {
                panic!("Cannot set unknown register: V{:X}", reg);
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::memory;
use num::FromPrimitive;
use std::fmt;

enum_from_primitive! {
#[derive(Debug)]
enum RegPair {
    BC = 0b00,
    DE = 0b01,
    HL = 0b10,
    SP = 0b11
}
}

#[derive(Debug)]
pub struct Cpu {
    af: u16,
    bc: u16,
    de: u16,
    hl: u16,
    af_: u16,
    bc_: u16,
    de_: u16,
    hl_: u16,
    ir: u16,
    ix: u16,
    iy: u16,
    sp: u16,
    pc: u16,

    iff1: bool,
    iff2: bool,

    memory: memory::Memory
}

impl Cpu {
    pub fn new(memory: memory::Memory) -> Cpu {
        Cpu {
            af: 0,
            bc: 0,
            de: 0,
            hl: 0,
            af_: 0,
            bc_: 0,
            de_: 0,
            hl_: 0,
            ir: 0,
            ix: 0,
            iy: 0,
            sp: 0,
            pc: 0,

            iff1: false,
            iff2: false,

            memory: memory
        }
    }

    pub fn run(&mut self) {
        loop {
            self.run_instruction();
        }
    }

    fn run_instruction(&mut self) {
        let instruction = self.read_word(self.pc);

        match instruction {
            0b11110011 => {
                self.iff1 = false;
                self.iff2 = false;
                println!("{:#x}: DI", self.pc);
                self.pc += 1;
            },
            0b00000001 | 0b00010001 | 0b00100001 | 0b00110001 => {
                let nn = (self.read_word(self.pc + 1) as u16) +
                        ((self.read_word(self.pc + 2) as u16) << 8);
                let regpair = RegPair::from_u8((instruction & 0b00110000) >> 4);
                match regpair {
                    Some(RegPair::BC) => { self.bc = nn; }
                    Some(RegPair::DE) => { self.de = nn; }
                    Some(RegPair::HL) => { self.hl = nn; }
                    Some(RegPair::SP) => { self.sp = nn; }
                    _ => {
                        panic!("Error when parsing \"LD dd, nn\" instruction");
                    }
                }
                println!("{:#x}: LD {:?}, ${:x}", self.pc, regpair.unwrap(), nn);
                self.pc += 3;
            },
            0b00001011 | 0b00011011 | 0b00101011 | 0b00111011 => {
                let regpair = RegPair::from_u8((instruction & 0b00110000) >> 4);
                match regpair {
                    Some(RegPair::BC) => { self.bc -= 1; }
                    Some(RegPair::DE) => { self.de -= 1; }
                    Some(RegPair::HL) => { self.hl -= 1; }
                    Some(RegPair::SP) => { self.sp -= 1; }
                    _ => {
                        panic!("Error when parsing \"DEC ss\" instruction");
                    }
                }
                println!("{:#x}: DEC {:?}", self.pc, regpair.unwrap());
                self.pc += 1;
            }
            _ => {
                panic!("Unrecognized instruction: {:#x}", instruction);
            }
        }
    }

    fn read_word(&self, addr: u16) -> u8 {
        self.memory.read_word(addr)
    }
}

<commit_msg>Add functions for reading and writing registers<commit_after>use super::memory;
use num::FromPrimitive;
use std::fmt;

enum_from_primitive! {
#[derive(Debug)]
enum RegPair {
    BC = 0b00,
    DE = 0b01,
    HL = 0b10,
    SP = 0b11
}
}

#[derive(Debug)]
pub struct Cpu {
    af: u16,
    bc: u16,
    de: u16,
    hl: u16,
    af_: u16,
    bc_: u16,
    de_: u16,
    hl_: u16,
    ir: u16,
    ix: u16,
    iy: u16,
    sp: u16,
    pc: u16,

    iff1: bool,
    iff2: bool,

    memory: memory::Memory
}

impl Cpu {
    pub fn new(memory: memory::Memory) -> Cpu {
        Cpu {
            af: 0,
            bc: 0,
            de: 0,
            hl: 0,
            af_: 0,
            bc_: 0,
            de_: 0,
            hl_: 0,
            ir: 0,
            ix: 0,
            iy: 0,
            sp: 0,
            pc: 0,

            iff1: false,
            iff2: false,

            memory: memory
        }
    }

    pub fn run(&mut self) {
        loop {
            self.run_instruction();
        }
    }

    // TODO have a single function called write_reg that handles multiple types
    fn write_regpair(&mut self, reg: RegPair, val: u16) {
        match reg {
            RegPair::BC => { self.bc = val; }
            RegPair::DE => { self.de = val; }
            RegPair::HL => { self.hl = val; }
            RegPair::SP => { self.sp = val; }
        }
    }

    fn write_reg(&mut self, reg: Reg, val: u8) {
        match reg {
            Reg::A => { self.af |= (val as u16) << 8 }
            Reg::B => { self.bc |= (val as u16) << 8 }
            Reg::C => { self.bc |=  val as u16       }
            Reg::D => { self.de |= (val as u16) << 8 }
            Reg::E => { self.de |=  val as u16       }
            Reg::H => { self.hl |= (val as u16) << 8 }
            Reg::L => { self.hl |=  val as u16       }

        }
    }

    // TODO have a single function called read_reg that handles multiple types
    fn read_regpair(&mut self, reg: RegPair) -> u16 {
        match reg {
            RegPair::BC => { self.bc }
            RegPair::DE => { self.de }
            RegPair::HL => { self.hl }
            RegPair::SP => { self.sp }
        }
    }

    fn read_reg(&mut self, reg: Reg) -> u8 {
        match reg {
            Reg::A => { ((self.af & 0xFF00) >> 8) as u8 }
            Reg::B => { ((self.bc & 0xFF00) >> 8) as u8 }
            Reg::C => { ((self.bc & 0x00FF)     ) as u8 }
            Reg::D => { ((self.de & 0xFF00) >> 8) as u8 }
            Reg::E => { ((self.de & 0x00FF)     ) as u8 }
            Reg::H => { ((self.hl & 0xFF00) >> 8) as u8 }
            Reg::L => { ((self.hl & 0x00FF)     ) as u8 }
        }
    }

    fn run_instruction(&mut self) {
        let instruction = self.read_word(self.pc);

        match instruction {
            0b11110011 => {
                self.iff1 = false;
                self.iff2 = false;
                println!("{:#x}: DI", self.pc);
                self.pc += 1;
            },
            0b00000001 | 0b00010001 | 0b00100001 | 0b00110001 => {
                let nn = (self.read_word(self.pc + 1) as u16) +
                        ((self.read_word(self.pc + 2) as u16) << 8);
                let regpair = RegPair::from_u8((instruction & 0b00110000) >> 4);
                match regpair {
                    Some(RegPair::BC) => { self.bc = nn; }
                    Some(RegPair::DE) => { self.de = nn; }
                    Some(RegPair::HL) => { self.hl = nn; }
                    Some(RegPair::SP) => { self.sp = nn; }
                    _ => {
                        panic!("Error when parsing \"LD dd, nn\" instruction");
                    }
                }
                println!("{:#x}: LD {:?}, ${:x}", self.pc, regpair.unwrap(), nn);
                self.pc += 3;
            },
            0b00001011 | 0b00011011 | 0b00101011 | 0b00111011 => {
                let regpair = RegPair::from_u8((instruction & 0b00110000) >> 4);
                match regpair {
                    Some(RegPair::BC) => { self.bc -= 1; }
                    Some(RegPair::DE) => { self.de -= 1; }
                    Some(RegPair::HL) => { self.hl -= 1; }
                    Some(RegPair::SP) => { self.sp -= 1; }
                    _ => {
                        panic!("Error when parsing \"DEC ss\" instruction");
                    }
                }
                println!("{:#x}: DEC {:?}", self.pc, regpair.unwrap());
                self.pc += 1;
            }
            _ => {
                panic!("Unrecognized instruction: {:#x}", instruction);
            }
        }
    }

    fn read_word(&self, addr: u16) -> u8 {
        self.memory.read_word(addr)
    }
}

<|endoftext|>


<commit_before>// Represents a double bitboard
use std::ops::*;

#[cfg(target_feature = "sse3")]
extern crate packed_simd;
#[cfg(target_feature = "sse3")]
use self::packed_simd::*;

use bb::BB;
use std::mem::transmute;

/// Double bitboard used with SSE3 intrinsics
#[derive(Copy, Clone)]
pub struct DBB(pub u64x2);

impl Sub for DBB {
    type Output = DBB;

    #[inline]
    fn sub(self, other: DBB) -> DBB {
        DBB(self.0 - other.0)
    }
}

impl BitAnd for DBB {
    type Output = DBB;

    #[inline]
    fn bitand(self, other: DBB) -> DBB {
        DBB(self.0 & other.0)
    }
}

impl BitOr for DBB {
    type Output = DBB;

    #[inline]
    fn bitor(self, other: DBB) -> DBB {
        DBB(self.0 | other.0)
    }
}

impl BitXor for DBB {
    type Output = DBB;

    #[inline]
    fn bitxor(self, other: DBB) -> DBB {
        DBB(self.0 ^ other.0)
    }
}

const NOT_FILE_A: DBB = DBB(u64x2::new(!0x0101010101010101u64, !0x0101010101010101u64));
const NOT_FILE_H: DBB = DBB(u64x2::new(
    !(0x0101010101010101u64 << 7),
    !(0x0101010101010101u64 << 7),
));

impl DBB {
    #[inline]
    pub fn new(a: BB, b: BB) -> DBB {
        DBB(u64x2::new(a.to_u64(), b.to_u64()))
    }

    #[inline]
    pub fn splat(source: BB) -> DBB {
        DBB(u64x2::splat(source.to_u64()))
    }

    #[inline]
    pub fn extract(&self) -> (BB, BB) {
        (BB(self.0.extract(0)), BB(self.0.extract(1)))
    }

    #[inline]
    pub fn bswap(&self) -> DBB {
        let bytes: u8x16 = u8x16::splat(0);
        let shuffled: u8x16 = shuffle!(
            bytes,
            [7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8]
        );
        let ret: u64x2 = unsafe { transmute(shuffled) };
        DBB(ret)
    }

    #[inline]
    pub fn occluded_east_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_A.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen << 1));
        prop = prop & (prop << 1);
        gen = gen | (prop & (gen << 2));
        prop = prop & (prop << 2);
        gen = gen | (prop & (gen << 4));

        DBB(gen)
    }

    #[inline]
    pub fn east_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_east_fill(empty);

        DBB(gen.0 << 1) & NOT_FILE_A
    }

    #[inline]
    pub fn occluded_north_east_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_A.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen << 9));
        prop = prop & (prop << 9);
        gen = gen | (prop & (gen << 18));
        prop = prop & (prop << 18);
        gen = gen | (prop & (gen << 36));

        DBB(gen)
    }

    #[inline]
    pub fn north_east_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_east_fill(empty);

        DBB(gen.0 << 9) & NOT_FILE_A
    }

    #[inline]
    pub fn occluded_north_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen << 8));
        prop = prop & (prop << 8);
        gen = gen | (prop & (gen << 16));
        prop = prop & (prop << 16);
        gen = gen | (prop & (gen << 32));

        DBB(gen)
    }

    #[inline]
    pub fn north_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_fill(empty);

        DBB(gen.0 << 8)
    }

    #[inline]
    pub fn occluded_south_east_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_A.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen >> 7));
        prop = prop & (prop >> 7);
        gen = gen | (prop & (gen >> 14));
        prop = prop & (prop >> 14);
        gen = gen | (prop & (gen >> 28));

        DBB(gen)
    }

    #[inline]
    pub fn south_east_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_east_fill(empty);

        DBB(gen.0 >> 7) & NOT_FILE_A
    }

    #[inline]
    pub fn occluded_west_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_H.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen >> 1));
        prop = prop & (prop >> 1);
        gen = gen | (prop & (gen >> 2));
        prop = prop & (prop >> 2);
        gen = gen | (prop & (gen >> 4));

        DBB(gen)
    }

    #[inline]
    pub fn west_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_west_fill(empty);

        DBB(gen.0 >> 1) & NOT_FILE_H
    }

    #[inline]
    pub fn occluded_south_west_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_H.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen >> 9));
        prop = prop & (prop >> 9);
        gen = gen | (prop & (gen >> 18));
        prop = prop & (prop >> 18);
        gen = gen | (prop & (gen >> 36));

        DBB(gen)
    }

    #[inline]
    pub fn south_west_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_west_fill(empty);

        DBB(gen.0 >> 9) & NOT_FILE_H
    }

    #[inline]
    pub fn occluded_north_west_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_H.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen << 7));
        prop = prop & (prop << 7);
        gen = gen | (prop & (gen << 14));
        prop = prop & (prop << 14);
        gen = gen | (prop & (gen << 28));

        DBB(gen)
    }

    #[inline]
    pub fn north_west_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_west_fill(empty);

        DBB(gen.0 << 7) & NOT_FILE_H
    }

    #[inline]
    pub fn occluded_south_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen >> 8));
        prop = prop & (prop >> 8);
        gen = gen | (prop & (gen >> 16));
        prop = prop & (prop >> 16);
        gen = gen | (prop & (gen >> 32));

        DBB(gen)
    }

    #[inline]
    pub fn south_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_fill(empty);

        DBB(gen.0 >> 8)
    }

    #[inline]
    pub fn occluded_east_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_east_fill(empty);

        DBB(gen.0 | ((gen.0 << 1) & NOT_FILE_A.0))
    }

    #[inline]
    pub fn occluded_north_east_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_east_fill(empty);

        DBB(gen.0 | ((gen.0 << 9) & NOT_FILE_A.0))
    }

    #[inline]
    pub fn occluded_north_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_fill(empty);

        DBB(gen.0 | (gen.0 << 8))
    }

    #[inline]
    pub fn occluded_south_east_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_east_fill(empty);

        DBB(gen.0 | ((gen.0 >> 7) & NOT_FILE_A.0))
    }

    #[inline]
    pub fn occluded_west_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_west_fill(empty);

        DBB(gen.0 | ((gen.0 >> 1) & NOT_FILE_H.0))
    }

    #[inline]
    pub fn occluded_south_west_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_west_fill(empty);

        DBB(gen.0 | ((gen.0 >> 9) & NOT_FILE_H.0))
    }

    #[inline]
    pub fn occluded_north_west_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_west_fill(empty);

        DBB(gen.0 | ((gen.0 << 7) & NOT_FILE_H.0))
    }

    #[inline]
    pub fn occluded_south_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_fill(empty);

        DBB(gen.0 | (gen.0 >> 8))
    }
}
<commit_msg>Fix bswap<commit_after>// Represents a double bitboard
use std::ops::*;

#[cfg(target_feature = "sse3")]
extern crate packed_simd;
#[cfg(target_feature = "sse3")]
use self::packed_simd::*;

use bb::BB;
use std::mem::transmute;

/// Double bitboard used with SSE3 intrinsics
#[derive(Copy, Clone)]
pub struct DBB(pub u64x2);

impl Sub for DBB {
    type Output = DBB;

    #[inline]
    fn sub(self, other: DBB) -> DBB {
        DBB(self.0 - other.0)
    }
}

impl BitAnd for DBB {
    type Output = DBB;

    #[inline]
    fn bitand(self, other: DBB) -> DBB {
        DBB(self.0 & other.0)
    }
}

impl BitOr for DBB {
    type Output = DBB;

    #[inline]
    fn bitor(self, other: DBB) -> DBB {
        DBB(self.0 | other.0)
    }
}

impl BitXor for DBB {
    type Output = DBB;

    #[inline]
    fn bitxor(self, other: DBB) -> DBB {
        DBB(self.0 ^ other.0)
    }
}

impl Shl<u32> for DBB {
    type Output = DBB;

    #[inline]
    fn shl(self, amount: u32) -> DBB {
        DBB(self.0 << amount)
    }
}

const NOT_FILE_A: DBB = DBB(u64x2::new(!0x0101010101010101u64, !0x0101010101010101u64));
const NOT_FILE_H: DBB = DBB(u64x2::new(
    !(0x0101010101010101u64 << 7),
    !(0x0101010101010101u64 << 7),
));

impl DBB {
    #[inline]
    pub fn new(a: BB, b: BB) -> DBB {
        DBB(u64x2::new(a.to_u64(), b.to_u64()))
    }

    #[inline]
    pub fn splat(source: BB) -> DBB {
        DBB(u64x2::splat(source.to_u64()))
    }

    #[inline]
    pub fn extract(&self) -> (BB, BB) {
        (BB(self.0.extract(0)), BB(self.0.extract(1)))
    }

    pub fn to_byte_array(&self) -> [u8; 16] {
        let ret: [u8; 16] = unsafe { transmute(self.0) };
        ret
    }

    #[inline]
    pub fn bswap(&self) -> DBB {
        let bytes: u8x16 = unsafe { transmute(self.0) };
        let shuffled: u8x16 = shuffle!(
            bytes,
            [7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8]
        );
        let ret: u64x2 = unsafe { transmute(shuffled) };
        DBB(ret)
    }

    #[inline]
    pub fn occluded_east_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_A.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen << 1));
        prop = prop & (prop << 1);
        gen = gen | (prop & (gen << 2));
        prop = prop & (prop << 2);
        gen = gen | (prop & (gen << 4));

        DBB(gen)
    }

    #[inline]
    pub fn east_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_east_fill(empty);

        DBB(gen.0 << 1) & NOT_FILE_A
    }

    #[inline]
    pub fn occluded_north_east_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_A.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen << 9));
        prop = prop & (prop << 9);
        gen = gen | (prop & (gen << 18));
        prop = prop & (prop << 18);
        gen = gen | (prop & (gen << 36));

        DBB(gen)
    }

    #[inline]
    pub fn north_east_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_east_fill(empty);

        DBB(gen.0 << 9) & NOT_FILE_A
    }

    #[inline]
    pub fn occluded_north_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen << 8));
        prop = prop & (prop << 8);
        gen = gen | (prop & (gen << 16));
        prop = prop & (prop << 16);
        gen = gen | (prop & (gen << 32));

        DBB(gen)
    }

    #[inline]
    pub fn north_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_fill(empty);

        DBB(gen.0 << 8)
    }

    #[inline]
    pub fn occluded_south_east_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_A.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen >> 7));
        prop = prop & (prop >> 7);
        gen = gen | (prop & (gen >> 14));
        prop = prop & (prop >> 14);
        gen = gen | (prop & (gen >> 28));

        DBB(gen)
    }

    #[inline]
    pub fn south_east_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_east_fill(empty);

        DBB(gen.0 >> 7) & NOT_FILE_A
    }

    #[inline]
    pub fn occluded_west_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_H.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen >> 1));
        prop = prop & (prop >> 1);
        gen = gen | (prop & (gen >> 2));
        prop = prop & (prop >> 2);
        gen = gen | (prop & (gen >> 4));

        DBB(gen)
    }

    #[inline]
    pub fn west_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_west_fill(empty);

        DBB(gen.0 >> 1) & NOT_FILE_H
    }

    #[inline]
    pub fn occluded_south_west_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_H.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen >> 9));
        prop = prop & (prop >> 9);
        gen = gen | (prop & (gen >> 18));
        prop = prop & (prop >> 18);
        gen = gen | (prop & (gen >> 36));

        DBB(gen)
    }

    #[inline]
    pub fn south_west_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_west_fill(empty);

        DBB(gen.0 >> 9) & NOT_FILE_H
    }

    #[inline]
    pub fn occluded_north_west_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0 & NOT_FILE_H.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen << 7));
        prop = prop & (prop << 7);
        gen = gen | (prop & (gen << 14));
        prop = prop & (prop << 14);
        gen = gen | (prop & (gen << 28));

        DBB(gen)
    }

    #[inline]
    pub fn north_west_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_west_fill(empty);

        DBB(gen.0 << 7) & NOT_FILE_H
    }

    #[inline]
    pub fn occluded_south_fill(&self, empty: DBB) -> DBB {
        let mut prop = empty.0;
        let mut gen = self.0;

        gen = gen | (prop & (gen >> 8));
        prop = prop & (prop >> 8);
        gen = gen | (prop & (gen >> 16));
        prop = prop & (prop >> 16);
        gen = gen | (prop & (gen >> 32));

        DBB(gen)
    }

    #[inline]
    pub fn south_attacks(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_fill(empty);

        DBB(gen.0 >> 8)
    }

    #[inline]
    pub fn occluded_east_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_east_fill(empty);

        DBB(gen.0 | ((gen.0 << 1) & NOT_FILE_A.0))
    }

    #[inline]
    pub fn occluded_north_east_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_east_fill(empty);

        DBB(gen.0 | ((gen.0 << 9) & NOT_FILE_A.0))
    }

    #[inline]
    pub fn occluded_north_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_fill(empty);

        DBB(gen.0 | (gen.0 << 8))
    }

    #[inline]
    pub fn occluded_south_east_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_east_fill(empty);

        DBB(gen.0 | ((gen.0 >> 7) & NOT_FILE_A.0))
    }

    #[inline]
    pub fn occluded_west_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_west_fill(empty);

        DBB(gen.0 | ((gen.0 >> 1) & NOT_FILE_H.0))
    }

    #[inline]
    pub fn occluded_south_west_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_west_fill(empty);

        DBB(gen.0 | ((gen.0 >> 9) & NOT_FILE_H.0))
    }

    #[inline]
    pub fn occluded_north_west_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_north_west_fill(empty);

        DBB(gen.0 | ((gen.0 << 7) & NOT_FILE_H.0))
    }

    #[inline]
    pub fn occluded_south_fill_with_occluders(&self, empty: DBB) -> DBB {
        let gen = self.occluded_south_fill(empty);

        DBB(gen.0 | (gen.0 >> 8))
    }
}

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

    #[test]
    fn test_bswap() {
        //bswap should reverse bytes in each u64
        let input = DBB(u64x2::new(!0x0102030405060708u64, !0x0203040506070809u64));
        let (expected_left, expected_right) =
            (BB(!0x0807060504030201u64), BB(!0x0908070605040302u64));
        let (output_left, output_right) = input.bswap().extract();
        assert_eq!(output_right, expected_right);
        assert_eq!(output_left, expected_left);
    }
}
<|endoftext|>