<commit_before>extern crate bincode;

use clap::{SubCommand, App, Arg, ArgMatches, ArgGroup};
use std::io::{stdin, stdout, Read};
use std::fs::File;

use lcfrs::Lcfrs;
use log_domain::LogDomain;
use lcfrs::cs_representation::CSRepresentation;
use lcfrs::cs_representation::automata::{PushDownGenerator, NaiveGenerator, ApproxGenerator, NaiveFilterAutomaton, InsideFilterAutomaton};
use util::agenda::Capacity;

use flate2::{read, write, Compression};

pub fn get_sub_command(name: &str) -> App {
    SubCommand::with_name(name)
                .about("Chomsky-Schützenberger representation of LCFRS")
                .subcommand(
                    SubCommand::with_name("extract")
                                .about("Reads a grammar from stdin and prints an object
                                       that Chomsky-Schützenberger-represents the grammar.")
                ).subcommand(
                    SubCommand::with_name("parse")
                                .about("Reads a list of words from stdin and parses them
                                       using the CS representation of a grammar.")
                                .arg(
                                    Arg::with_name("csfile")
                                        .required(true)
                                        .index(1)
                                        .help("The file that contains the CS representation of a grammar.")
                                ).arg(
                                    Arg::with_name("k")
                                        .short("k")
                                        .takes_value(true)
                                        .help("Puts the `k` in k-best parsing.")
                                ).arg(
                                    Arg::with_name("beam")
                                        .short("b").long("beam")
                                        .takes_value(true)
                                        .help("Beam with during search.")
                                ).arg(
                                    Arg::with_name("debugmode")
                                        .short("d").long("debug")
                                )
                ).group(
                    ArgGroup::with_name("strategy")
                ).arg(
                    Arg::with_name("naive")
                        .help("Use a naive Generator automaton.")
                        .long("naive")
                        .group("strategy")
                ).arg(
                    Arg::with_name("approx")
                        .help("Use a regular approximation the push-down generator.")
                        .long("approx")
                        .group("strategy")
                        .takes_value(true)
                ).arg(
                    Arg::with_name("pd")
                        .help("Use a push-down automaton to generate candidates.")
                        .long("pd")
                        .group("strategy")
                ).group(
                    ArgGroup::with_name("filter")
                ).arg(
                    Arg::with_name("naive-filter")
                        .help("Use a naive filter automaton.")
                        .long("naive-filter")
                        .group("filter")
                ).arg(
                    Arg::with_name("inside-filter")
                        .help("Use the inside filter automaton.")
                        .long("inside-filter")
                        .group("filter")
                )
}

pub fn handle_sub_matches(submatches: &ArgMatches) {
    enum Strat {
        Keller, Naive, Approx(usize)
    }
    enum Filter {
        Naive, Inside
    }

    let strategy = {
        if submatches.is_present("naive") {
            Strat::Naive
        } else if let Some(depth) = submatches.value_of("approx") {
                Strat::Approx(depth.parse().unwrap())
        } else {
            Strat::Keller
        }
    };
    let filter = {
        if submatches.is_present("naive-filter")  {
            Filter::Naive
        } else {
            Filter::Inside
        }
    };

    match submatches.subcommand() {
        ("extract", _) => {
            let mut grammar_string = String::new();
            stdin().read_to_string(&mut grammar_string).expect(
                "Could not read from stdin. Be sure to provide the gramar file as input.",
            );
            let grammar: Lcfrs<String, String, LogDomain<f64>> = grammar_string.parse().expect(
                "Could not decode the grammar provided via stdin.",
            );

            match (strategy, filter) {
                (Strat::Keller, Filter::Inside) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, InsideFilterAutomaton<String>, PushDownGenerator>::new(PushDownGenerator, grammar),
                        bincode::Infinite
                    ).unwrap()
                }, (Strat::Naive, Filter::Inside) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, InsideFilterAutomaton<String>, NaiveGenerator>::new(NaiveGenerator, grammar),
                        bincode::Infinite
                    ).unwrap()
                }, (Strat::Approx(d), Filter::Inside) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, InsideFilterAutomaton<String>, ApproxGenerator>::new(ApproxGenerator(d), grammar),
                        bincode::Infinite
                    ).unwrap()
                },(Strat::Keller, Filter::Naive) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, NaiveFilterAutomaton<String>, PushDownGenerator>::new(PushDownGenerator, grammar),
                        bincode::Infinite
                    ).unwrap()
                }, (Strat::Naive, Filter::Naive) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, NaiveFilterAutomaton<String>, NaiveGenerator>::new(NaiveGenerator, grammar),
                        bincode::Infinite
                    ).unwrap()
                }, (Strat::Approx(d), Filter::Naive) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, NaiveFilterAutomaton<String>, ApproxGenerator>::new(ApproxGenerator(d), grammar),
                        bincode::Infinite
                    ).unwrap()
                }
            }
        }

        ("parse", Some(params)) => {
            let mut word_strings = String::new();
            stdin().read_to_string(&mut word_strings).expect(
                "Please pass a string to parse using stdin or using the `--word` option.",
            );
            let k: usize = match params.value_of("k") {
                Some(n) => n.parse::<usize>().unwrap(),
                None => 1usize,
            };
            let beam: Capacity = match params.value_of("beam") {
                Some(b) => Capacity::Limit(b.parse().unwrap()),
                None => Capacity::Infinite,
            };
            let csfile = File::open(params.value_of("csfile").unwrap()).unwrap();

            match (strategy, filter) {
                (Strat::Keller, Filter::Inside) => {
                    let csrep: CSRepresentation<String, String, InsideFilterAutomaton<String>, PushDownGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for (sentence_id, sentence) in word_strings.lines().enumerate() {
                        let words: Vec<String> = sentence.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                println!("#BOS {} 0 0 0 0", sentence_id + 1);
                                print!("{}", derivation);
                                println!("#EOS {}", sentence_id + 1);
                            }
                        }
                    }
                }, (Strat::Naive, Filter::Inside) => {
                    let csrep: CSRepresentation<String, String, InsideFilterAutomaton<String>, NaiveGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for line in word_strings.lines() {
                        let words: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                println!("{}", derivation);
                            }
                        }
                    }
                }, (Strat::Approx(_), Filter::Inside) => {
                    let csrep: CSRepresentation<String, String, InsideFilterAutomaton<String>, ApproxGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for line in word_strings.lines() {
                        let words: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                println!("{}", derivation);
                            }
                        }
                    }
                }, (Strat::Keller, Filter::Naive) => {
                    let csrep: CSRepresentation<String, String, NaiveFilterAutomaton<String>, PushDownGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for line in word_strings.lines() {
                        let words: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                println!("{}", derivation);
                            }
                        }
                    }
                }, (Strat::Naive, Filter::Naive) => {
                    let csrep: CSRepresentation<String, String, NaiveFilterAutomaton<String>, NaiveGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for line in word_strings.lines() {
                        let words: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                println!("{}", derivation);
                            }
                        }
                    }
                }, (Strat::Approx(_), Filter::Naive) => {
                    let csrep: CSRepresentation<String, String, NaiveFilterAutomaton<String>, ApproxGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for line in word_strings.lines() {
                        let words: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                println!("{}", derivation);
                            }
                        }
                    }
                },
            }
        },
        _ => (),
    }
}
<commit_msg>remove bos/eos output<commit_after>extern crate bincode;

use clap::{SubCommand, App, Arg, ArgMatches, ArgGroup};
use std::io::{stdin, stdout, Read};
use std::fs::File;

use lcfrs::Lcfrs;
use log_domain::LogDomain;
use lcfrs::cs_representation::CSRepresentation;
use lcfrs::cs_representation::automata::{PushDownGenerator, NaiveGenerator, ApproxGenerator, NaiveFilterAutomaton, InsideFilterAutomaton};
use util::agenda::Capacity;

use flate2::{read, write, Compression};

pub fn get_sub_command(name: &str) -> App {
    SubCommand::with_name(name)
                .about("Chomsky-Schützenberger representation of LCFRS")
                .subcommand(
                    SubCommand::with_name("extract")
                                .about("Reads a grammar from stdin and prints an object
                                       that Chomsky-Schützenberger-represents the grammar.")
                ).subcommand(
                    SubCommand::with_name("parse")
                                .about("Reads a list of words from stdin and parses them
                                       using the CS representation of a grammar.")
                                .arg(
                                    Arg::with_name("csfile")
                                        .required(true)
                                        .index(1)
                                        .help("The file that contains the CS representation of a grammar.")
                                ).arg(
                                    Arg::with_name("k")
                                        .short("k")
                                        .takes_value(true)
                                        .help("Puts the `k` in k-best parsing.")
                                ).arg(
                                    Arg::with_name("beam")
                                        .short("b").long("beam")
                                        .takes_value(true)
                                        .help("Beam with during search.")
                                ).arg(
                                    Arg::with_name("debugmode")
                                        .short("d").long("debug")
                                )
                ).group(
                    ArgGroup::with_name("strategy")
                ).arg(
                    Arg::with_name("naive")
                        .help("Use a naive Generator automaton.")
                        .long("naive")
                        .group("strategy")
                ).arg(
                    Arg::with_name("approx")
                        .help("Use a regular approximation the push-down generator.")
                        .long("approx")
                        .group("strategy")
                        .takes_value(true)
                ).arg(
                    Arg::with_name("pd")
                        .help("Use a push-down automaton to generate candidates.")
                        .long("pd")
                        .group("strategy")
                ).group(
                    ArgGroup::with_name("filter")
                ).arg(
                    Arg::with_name("naive-filter")
                        .help("Use a naive filter automaton.")
                        .long("naive-filter")
                        .group("filter")
                ).arg(
                    Arg::with_name("inside-filter")
                        .help("Use the inside filter automaton.")
                        .long("inside-filter")
                        .group("filter")
                )
}

pub fn handle_sub_matches(submatches: &ArgMatches) {
    enum Strat {
        Keller, Naive, Approx(usize)
    }
    enum Filter {
        Naive, Inside
    }

    let strategy = {
        if submatches.is_present("naive") {
            Strat::Naive
        } else if let Some(depth) = submatches.value_of("approx") {
                Strat::Approx(depth.parse().unwrap())
        } else {
            Strat::Keller
        }
    };
    let filter = {
        if submatches.is_present("naive-filter")  {
            Filter::Naive
        } else {
            Filter::Inside
        }
    };

    match submatches.subcommand() {
        ("extract", _) => {
            let mut grammar_string = String::new();
            stdin().read_to_string(&mut grammar_string).expect(
                "Could not read from stdin. Be sure to provide the gramar file as input.",
            );
            let grammar: Lcfrs<String, String, LogDomain<f64>> = grammar_string.parse().expect(
                "Could not decode the grammar provided via stdin.",
            );

            match (strategy, filter) {
                (Strat::Keller, Filter::Inside) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, InsideFilterAutomaton<String>, PushDownGenerator>::new(PushDownGenerator, grammar),
                        bincode::Infinite
                    ).unwrap()
                }, (Strat::Naive, Filter::Inside) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, InsideFilterAutomaton<String>, NaiveGenerator>::new(NaiveGenerator, grammar),
                        bincode::Infinite
                    ).unwrap()
                }, (Strat::Approx(d), Filter::Inside) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, InsideFilterAutomaton<String>, ApproxGenerator>::new(ApproxGenerator(d), grammar),
                        bincode::Infinite
                    ).unwrap()
                },(Strat::Keller, Filter::Naive) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, NaiveFilterAutomaton<String>, PushDownGenerator>::new(PushDownGenerator, grammar),
                        bincode::Infinite
                    ).unwrap()
                }, (Strat::Naive, Filter::Naive) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, NaiveFilterAutomaton<String>, NaiveGenerator>::new(NaiveGenerator, grammar),
                        bincode::Infinite
                    ).unwrap()
                }, (Strat::Approx(d), Filter::Naive) => {
                    bincode::serialize_into(
                        &mut write::GzEncoder::new(stdout(), Compression::best()),
                        &CSRepresentation::<String, String, NaiveFilterAutomaton<String>, ApproxGenerator>::new(ApproxGenerator(d), grammar),
                        bincode::Infinite
                    ).unwrap()
                }
            }
        }

        ("parse", Some(params)) => {
            let mut word_strings = String::new();
            stdin().read_to_string(&mut word_strings).expect(
                "Please pass a string to parse using stdin or using the `--word` option.",
            );
            let k: usize = match params.value_of("k") {
                Some(n) => n.parse::<usize>().unwrap(),
                None => 1usize,
            };
            let beam: Capacity = match params.value_of("beam") {
                Some(b) => Capacity::Limit(b.parse().unwrap()),
                None => Capacity::Infinite,
            };
            let csfile = File::open(params.value_of("csfile").unwrap()).unwrap();

            match (strategy, filter) {
                (Strat::Keller, Filter::Inside) => {
                    let csrep: CSRepresentation<String, String, InsideFilterAutomaton<String>, PushDownGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for (sentence_id, sentence) in word_strings.lines().enumerate() {
                        let words: Vec<String> = sentence.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                print!("{}", derivation);
                            }
                        }
                    }
                }, (Strat::Naive, Filter::Inside) => {
                    let csrep: CSRepresentation<String, String, InsideFilterAutomaton<String>, NaiveGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for line in word_strings.lines() {
                        let words: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                println!("{}", derivation);
                            }
                        }
                    }
                }, (Strat::Approx(_), Filter::Inside) => {
                    let csrep: CSRepresentation<String, String, InsideFilterAutomaton<String>, ApproxGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for line in word_strings.lines() {
                        let words: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                println!("{}", derivation);
                            }
                        }
                    }
                }, (Strat::Keller, Filter::Naive) => {
                    let csrep: CSRepresentation<String, String, NaiveFilterAutomaton<String>, PushDownGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for line in word_strings.lines() {
                        let words: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                println!("{}", derivation);
                            }
                        }
                    }
                }, (Strat::Naive, Filter::Naive) => {
                    let csrep: CSRepresentation<String, String, NaiveFilterAutomaton<String>, NaiveGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for line in word_strings.lines() {
                        let words: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                println!("{}", derivation);
                            }
                        }
                    }
                }, (Strat::Approx(_), Filter::Naive) => {
                    let csrep: CSRepresentation<String, String, NaiveFilterAutomaton<String>, ApproxGenerator> = bincode::deserialize_from(&mut read::GzDecoder::new(csfile), bincode::Infinite).unwrap();
                    for line in word_strings.lines() {
                        let words: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();

                        if params.is_present("debugmode") {
                            csrep.debug(words.as_slice(), beam);
                        } else {
                            for derivation in csrep.generate(words.as_slice(), beam).take(k) {
                                println!("{}", derivation);
                            }
                        }
                    }
                },
            }
        },
        _ => (),
    }
}
<|endoftext|>


<commit_before>//! This module contains the `InterpCx` methods for executing a single step of the interpreter.
//!
//! The main entry point is the `step` method.

use rustc::mir;
use rustc::ty::layout::LayoutOf;
use rustc::mir::interpret::{InterpResult, Scalar, PointerArithmetic};

use super::{InterpCx, Machine};

/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
/// same type as the result.
#[inline]
fn binop_left_homogeneous(op: mir::BinOp) -> bool {
    use rustc::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr |
        Offset | Shl | Shr =>
            true,
        Eq | Ne | Lt | Le | Gt | Ge =>
            false,
    }
}
/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the
/// same type as the LHS.
#[inline]
fn binop_right_homogeneous(op: mir::BinOp) -> bool {
    use rustc::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr |
        Eq | Ne | Lt | Le | Gt | Ge =>
            true,
        Offset | Shl | Shr =>
            false,
    }
}

impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
    pub fn run(&mut self) -> InterpResult<'tcx> {
        while self.step()? {}
        Ok(())
    }

    /// Returns `true` as long as there are more things to do.
    ///
    /// This is used by [priroda](https://github.com/oli-obk/priroda)
    pub fn step(&mut self) -> InterpResult<'tcx, bool> {
        if self.stack.is_empty() {
            return Ok(false);
        }

        let block = match self.frame().block {
            Some(block) => block,
            None => {
                // We are unwinding and this fn has no cleanup code.
                // Just go on unwinding.
                trace!("unwinding: skipping frame");
                self.pop_stack_frame(/* unwinding */ true)?;
                return Ok(true)
            }
        };
        let stmt_id = self.frame().stmt;
        let body = self.body();
        let basic_block = &body.basic_blocks()[block];

        let old_frames = self.cur_frame();

        if let Some(stmt) = basic_block.statements.get(stmt_id) {
            assert_eq!(old_frames, self.cur_frame());
            self.statement(stmt)?;
            return Ok(true);
        }

        M::before_terminator(self)?;

        let terminator = basic_block.terminator();
        assert_eq!(old_frames, self.cur_frame());
        self.terminator(terminator)?;
        Ok(true)
    }

    fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", stmt);

        use rustc::mir::StatementKind::*;

        // Some statements (e.g., box) push new stack frames.
        // We have to record the stack frame number *before* executing the statement.
        let frame_idx = self.cur_frame();
        self.tcx.span = stmt.source_info.span;
        self.memory.tcx.span = stmt.source_info.span;

        match stmt.kind {
            Assign(box(ref place, ref rvalue)) => self.eval_rvalue_into_place(rvalue, place)?,

            SetDiscriminant {
                ref place,
                variant_index,
            } => {
                let dest = self.eval_place(place)?;
                self.write_discriminant_index(variant_index, dest)?;
            }

            // Mark locals as alive
            StorageLive(local) => {
                let old_val = self.storage_live(local)?;
                self.deallocate_local(old_val)?;
            }

            // Mark locals as dead
            StorageDead(local) => {
                let old_val = self.storage_dead(local);
                self.deallocate_local(old_val)?;
            }

            // No dynamic semantics attached to `FakeRead`; MIR
            // interpreter is solely intended for borrowck'ed code.
            FakeRead(..) => {}

            // Stacked Borrows.
            Retag(kind, ref place) => {
                let dest = self.eval_place(place)?;
                M::retag(self, kind, dest)?;
            }

            // Statements we do not track.
            AscribeUserType(..) => {}

            // Defined to do nothing. These are added by optimization passes, to avoid changing the
            // size of MIR constantly.
            Nop => {}

            InlineAsm { .. } => throw_unsup_format!("inline assembly is not supported"),
        }

        self.stack[frame_idx].stmt += 1;
        Ok(())
    }

    /// Evaluate an assignment statement.
    ///
    /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
    /// type writes its results directly into the memory specified by the place.
    pub fn eval_rvalue_into_place(
        &mut self,
        rvalue: &mir::Rvalue<'tcx>,
        place: &mir::Place<'tcx>,
    ) -> InterpResult<'tcx> {
        let dest = self.eval_place(place)?;

        use rustc::mir::Rvalue::*;
        match *rvalue {
            Use(ref operand) => {
                // Avoid recomputing the layout
                let op = self.eval_operand(operand, Some(dest.layout))?;
                self.copy_op(op, dest)?;
            }

            BinaryOp(bin_op, ref left, ref right) => {
                let layout = binop_left_homogeneous(bin_op).then_some(dest.layout);
                let left = self.read_immediate(self.eval_operand(left, layout)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(self.eval_operand(right, layout)?)?;
                self.binop_ignore_overflow(
                    bin_op,
                    left,
                    right,
                    dest,
                )?;
            }

            CheckedBinaryOp(bin_op, ref left, ref right) => {
                // Due to the extra boolean in the result, we can never reuse the `dest.layout`.
                let left = self.read_immediate(self.eval_operand(left, None)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(self.eval_operand(right, layout)?)?;
                self.binop_with_overflow(
                    bin_op,
                    left,
                    right,
                    dest,
                )?;
            }

            UnaryOp(un_op, ref operand) => {
                // The operand always has the same type as the result.
                let val = self.read_immediate(self.eval_operand(operand, Some(dest.layout))?)?;
                let val = self.unary_op(un_op, val)?;
                assert_eq!(val.layout, dest.layout, "layout mismatch for result of {:?}", un_op);
                self.write_immediate(*val, dest)?;
            }

            Aggregate(ref kind, ref operands) => {
                let (dest, active_field_index) = match **kind {
                    mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
                        self.write_discriminant_index(variant_index, dest)?;
                        if adt_def.is_enum() {
                            (self.place_downcast(dest, variant_index)?, active_field_index)
                        } else {
                            (dest, active_field_index)
                        }
                    }
                    _ => (dest, None)
                };

                for (i, operand) in operands.iter().enumerate() {
                    let op = self.eval_operand(operand, None)?;
                    // Ignore zero-sized fields.
                    if !op.layout.is_zst() {
                        let field_index = active_field_index.unwrap_or(i);
                        let field_dest = self.place_field(dest, field_index as u64)?;
                        self.copy_op(op, field_dest)?;
                    }
                }
            }

            Repeat(ref operand, _) => {
                let op = self.eval_operand(operand, None)?;
                let dest = self.force_allocation(dest)?;
                let length = dest.len(self)?;

                if let Some(first_ptr) = self.check_mplace_access(dest, None)? {
                    // Write the first.
                    let first = self.mplace_field(dest, 0)?;
                    self.copy_op(op, first.into())?;

                    if length > 1 {
                        let elem_size = first.layout.size;
                        // Copy the rest. This is performance-sensitive code
                        // for big static/const arrays!
                        let rest_ptr = first_ptr.offset(elem_size, self)?;
                        self.memory.copy_repeatedly(
                            first_ptr, rest_ptr, elem_size, length - 1, /*nonoverlapping:*/true
                        )?;
                    }
                }
            }

            Len(ref place) => {
                // FIXME(CTFE): don't allow computing the length of arrays in const eval
                let src = self.eval_place(place)?;
                let mplace = self.force_allocation(src)?;
                let len = mplace.len(self)?;
                let size = self.pointer_size();
                self.write_scalar(
                    Scalar::from_uint(len, size),
                    dest,
                )?;
            }

            Ref(_, _, ref place) => {
                let src = self.eval_place(place)?;
                let place = self.force_allocation(src)?;
                if place.layout.size.bytes() > 0 {
                    // definitely not a ZST
                    assert!(place.ptr.is_ptr(), "non-ZST places should be normalized to `Pointer`");
                }
                self.write_immediate(place.to_ref(), dest)?;
            }

            NullaryOp(mir::NullOp::Box, _) => {
                M::box_alloc(self, dest)?;
            }

            NullaryOp(mir::NullOp::SizeOf, ty) => {
                let ty = self.subst_from_frame_and_normalize_erasing_regions(ty);
                let layout = self.layout_of(ty)?;
                assert!(!layout.is_unsized(),
                        "SizeOf nullary MIR operator called for unsized type");
                let size = self.pointer_size();
                self.write_scalar(
                    Scalar::from_uint(layout.size.bytes(), size),
                    dest,
                )?;
            }

            Cast(kind, ref operand, _) => {
                let src = self.eval_operand(operand, None)?;
                self.cast(src, kind, dest)?;
            }

            Discriminant(ref place) => {
                let op = self.eval_place_to_op(place, None)?;
                let discr_val = self.read_discriminant(op)?.0;
                let size = dest.layout.size;
                self.write_scalar(Scalar::from_uint(discr_val, size), dest)?;
            }
        }

        self.dump_place(*dest);

        Ok(())
    }

    fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", terminator.kind);
        self.tcx.span = terminator.source_info.span;
        self.memory.tcx.span = terminator.source_info.span;

        let old_stack = self.cur_frame();
        let old_bb = self.frame().block;

        self.eval_terminator(terminator)?;
        if !self.stack.is_empty() {
            // This should change *something*
            debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb);
            info!("// {:?}", self.frame().block);
        }
        Ok(())
    }
}
<commit_msg>Rollup merge of #67145 - RalfJung:miri-step, r=oli-obk<commit_after>//! This module contains the `InterpCx` methods for executing a single step of the interpreter.
//!
//! The main entry point is the `step` method.

use rustc::mir;
use rustc::ty::layout::LayoutOf;
use rustc::mir::interpret::{InterpResult, Scalar, PointerArithmetic};

use super::{InterpCx, Machine};

/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
/// same type as the result.
#[inline]
fn binop_left_homogeneous(op: mir::BinOp) -> bool {
    use rustc::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr |
        Offset | Shl | Shr =>
            true,
        Eq | Ne | Lt | Le | Gt | Ge =>
            false,
    }
}
/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the
/// same type as the LHS.
#[inline]
fn binop_right_homogeneous(op: mir::BinOp) -> bool {
    use rustc::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr |
        Eq | Ne | Lt | Le | Gt | Ge =>
            true,
        Offset | Shl | Shr =>
            false,
    }
}

impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
    pub fn run(&mut self) -> InterpResult<'tcx> {
        while self.step()? {}
        Ok(())
    }

    /// Returns `true` as long as there are more things to do.
    ///
    /// This is used by [priroda](https://github.com/oli-obk/priroda)
    pub fn step(&mut self) -> InterpResult<'tcx, bool> {
        if self.stack.is_empty() {
            return Ok(false);
        }

        let block = match self.frame().block {
            Some(block) => block,
            None => {
                // We are unwinding and this fn has no cleanup code.
                // Just go on unwinding.
                trace!("unwinding: skipping frame");
                self.pop_stack_frame(/* unwinding */ true)?;
                return Ok(true)
            }
        };
        let stmt_id = self.frame().stmt;
        let body = self.body();
        let basic_block = &body.basic_blocks()[block];

        let old_frames = self.cur_frame();

        if let Some(stmt) = basic_block.statements.get(stmt_id) {
            assert_eq!(old_frames, self.cur_frame());
            self.statement(stmt)?;
            return Ok(true);
        }

        M::before_terminator(self)?;

        let terminator = basic_block.terminator();
        assert_eq!(old_frames, self.cur_frame());
        self.terminator(terminator)?;
        Ok(true)
    }

    fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", stmt);

        use rustc::mir::StatementKind::*;

        // Some statements (e.g., box) push new stack frames.
        // We have to record the stack frame number *before* executing the statement.
        let frame_idx = self.cur_frame();
        self.tcx.span = stmt.source_info.span;
        self.memory.tcx.span = stmt.source_info.span;

        match stmt.kind {
            Assign(box(ref place, ref rvalue)) => self.eval_rvalue_into_place(rvalue, place)?,

            SetDiscriminant {
                ref place,
                variant_index,
            } => {
                let dest = self.eval_place(place)?;
                self.write_discriminant_index(variant_index, dest)?;
            }

            // Mark locals as alive
            StorageLive(local) => {
                let old_val = self.storage_live(local)?;
                self.deallocate_local(old_val)?;
            }

            // Mark locals as dead
            StorageDead(local) => {
                let old_val = self.storage_dead(local);
                self.deallocate_local(old_val)?;
            }

            // No dynamic semantics attached to `FakeRead`; MIR
            // interpreter is solely intended for borrowck'ed code.
            FakeRead(..) => {}

            // Stacked Borrows.
            Retag(kind, ref place) => {
                let dest = self.eval_place(place)?;
                M::retag(self, kind, dest)?;
            }

            // Statements we do not track.
            AscribeUserType(..) => {}

            // Defined to do nothing. These are added by optimization passes, to avoid changing the
            // size of MIR constantly.
            Nop => {}

            InlineAsm { .. } => throw_unsup_format!("inline assembly is not supported"),
        }

        self.stack[frame_idx].stmt += 1;
        Ok(())
    }

    /// Evaluate an assignment statement.
    ///
    /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
    /// type writes its results directly into the memory specified by the place.
    pub fn eval_rvalue_into_place(
        &mut self,
        rvalue: &mir::Rvalue<'tcx>,
        place: &mir::Place<'tcx>,
    ) -> InterpResult<'tcx> {
        let dest = self.eval_place(place)?;

        use rustc::mir::Rvalue::*;
        match *rvalue {
            Use(ref operand) => {
                // Avoid recomputing the layout
                let op = self.eval_operand(operand, Some(dest.layout))?;
                self.copy_op(op, dest)?;
            }

            BinaryOp(bin_op, ref left, ref right) => {
                let layout = binop_left_homogeneous(bin_op).then_some(dest.layout);
                let left = self.read_immediate(self.eval_operand(left, layout)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(self.eval_operand(right, layout)?)?;
                self.binop_ignore_overflow(
                    bin_op,
                    left,
                    right,
                    dest,
                )?;
            }

            CheckedBinaryOp(bin_op, ref left, ref right) => {
                // Due to the extra boolean in the result, we can never reuse the `dest.layout`.
                let left = self.read_immediate(self.eval_operand(left, None)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(self.eval_operand(right, layout)?)?;
                self.binop_with_overflow(
                    bin_op,
                    left,
                    right,
                    dest,
                )?;
            }

            UnaryOp(un_op, ref operand) => {
                // The operand always has the same type as the result.
                let val = self.read_immediate(self.eval_operand(operand, Some(dest.layout))?)?;
                let val = self.unary_op(un_op, val)?;
                assert_eq!(val.layout, dest.layout, "layout mismatch for result of {:?}", un_op);
                self.write_immediate(*val, dest)?;
            }

            Aggregate(ref kind, ref operands) => {
                let (dest, active_field_index) = match **kind {
                    mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
                        self.write_discriminant_index(variant_index, dest)?;
                        if adt_def.is_enum() {
                            (self.place_downcast(dest, variant_index)?, active_field_index)
                        } else {
                            (dest, active_field_index)
                        }
                    }
                    _ => (dest, None)
                };

                for (i, operand) in operands.iter().enumerate() {
                    let op = self.eval_operand(operand, None)?;
                    // Ignore zero-sized fields.
                    if !op.layout.is_zst() {
                        let field_index = active_field_index.unwrap_or(i);
                        let field_dest = self.place_field(dest, field_index as u64)?;
                        self.copy_op(op, field_dest)?;
                    }
                }
            }

            Repeat(ref operand, _) => {
                let op = self.eval_operand(operand, None)?;
                let dest = self.force_allocation(dest)?;
                let length = dest.len(self)?;

                if let Some(first_ptr) = self.check_mplace_access(dest, None)? {
                    // Write the first.
                    let first = self.mplace_field(dest, 0)?;
                    self.copy_op(op, first.into())?;

                    if length > 1 {
                        let elem_size = first.layout.size;
                        // Copy the rest. This is performance-sensitive code
                        // for big static/const arrays!
                        let rest_ptr = first_ptr.offset(elem_size, self)?;
                        self.memory.copy_repeatedly(
                            first_ptr, rest_ptr, elem_size, length - 1, /*nonoverlapping:*/true
                        )?;
                    }
                }
            }

            Len(ref place) => {
                // FIXME(CTFE): don't allow computing the length of arrays in const eval
                let src = self.eval_place(place)?;
                let mplace = self.force_allocation(src)?;
                let len = mplace.len(self)?;
                let size = self.pointer_size();
                self.write_scalar(
                    Scalar::from_uint(len, size),
                    dest,
                )?;
            }

            Ref(_, _, ref place) => {
                let src = self.eval_place(place)?;
                let place = self.force_allocation(src)?;
                if place.layout.size.bytes() > 0 {
                    // definitely not a ZST
                    assert!(place.ptr.is_ptr(), "non-ZST places should be normalized to `Pointer`");
                }
                self.write_immediate(place.to_ref(), dest)?;
            }

            NullaryOp(mir::NullOp::Box, _) => {
                M::box_alloc(self, dest)?;
            }

            NullaryOp(mir::NullOp::SizeOf, ty) => {
                let ty = self.subst_from_frame_and_normalize_erasing_regions(ty);
                let layout = self.layout_of(ty)?;
                assert!(!layout.is_unsized(),
                        "SizeOf nullary MIR operator called for unsized type");
                let size = self.pointer_size();
                self.write_scalar(
                    Scalar::from_uint(layout.size.bytes(), size),
                    dest,
                )?;
            }

            Cast(kind, ref operand, _) => {
                let src = self.eval_operand(operand, None)?;
                self.cast(src, kind, dest)?;
            }

            Discriminant(ref place) => {
                let op = self.eval_place_to_op(place, None)?;
                let discr_val = self.read_discriminant(op)?.0;
                let size = dest.layout.size;
                self.write_scalar(Scalar::from_uint(discr_val, size), dest)?;
            }
        }

        self.dump_place(*dest);

        Ok(())
    }

    fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", terminator.kind);
        self.tcx.span = terminator.source_info.span;
        self.memory.tcx.span = terminator.source_info.span;

        let old_stack = self.cur_frame();
        let old_bb = self.frame().block;

        self.eval_terminator(terminator)?;
        if !self.stack.is_empty() {
            // This should change *something*
            debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb);
            if let Some(block) = self.frame().block {
                info!("// executing {:?}", block);
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>#[macro_use]
mod mask_macros;

mod mask16;
mod mask32;
mod mask64;
mod mask8;
mod masksize;
<commit_msg>Fix rustfmt<commit_after>#[macro_use]
mod mask_macros;

#[rustfmt::skip]
mod mask8;
mod mask16;
mod mask32;
mod mask64;
mod masksize;
<|endoftext|>


<commit_before>use core::cmp::{Eq, Ord};

pub trait Map<K: Copy Eq Ord, V: Copy> {
  pure fn get(k: K) -> @Option<V>;
  pure fn put(k: K, v: V) -> self;
  pure fn delete(k: K) -> self;
}

enum RBColor {
  Red,
  Black
}

pub enum RBMap<K: Copy Eq Ord, V: Copy> {
  //   color    left         k  value       right
  Tree(RBColor, @RBMap<K,V>, K, @Option<V>, @RBMap<K,V>),
  Leaf
}

pure fn RBMap<K: Copy Eq Ord, V: Copy>(key: K, value: V) -> @RBMap<K, V> {
  @Tree(Red, @Leaf, key, @Some(value), @Leaf)
}

/**
 * A purely functional Red-Black tree.
 *
 * A port of Matt Might's Scala port of Okasaki's RB Trees: http://matt.might.net/articles/implementation-of-immutable-purely-functional-okasaki-red-black-tree-maps-in-scala/RBMap.scala
 * which was itself a port of http://www.ccs.neu.edu/course/cs3500wc/jfp99redblack.pdf
 */
impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> : Map<K, V> {
  pure fn get(k: K) -> @Option<V> {
    match self {
      @Leaf => @None,
      @Tree(_, left, key, maybe_value, right) => {
        if (k.lt(&key)) {
          left.get(k)
        } else if (k.gt(&key)) {
          right.get(k)
        } else {
          maybe_value
        }
      }
    }
  }

  pure fn put(k : K, v : V) -> @RBMap<K, V> {
    self.modifiedWith(k, |m,n| { @Some(v) })
  }

  pure fn delete(k: K) -> @RBMap<K, V> {
    self.modifiedWith(k, |m,n| { @None })
  }

  priv pure fn blacken(n : @RBMap<K, V>) -> @RBMap<K, V> {
    match n {
      @Leaf => n,
      @Tree(_,l,k,v,r) => @Tree(Black,l,k,v,r)
    }
  }

  priv pure fn modifiedWith (k : K, f : fn(K, @Option<V>) -> @Option<V>) -> @RBMap<K, V> {
    self.blacken(self.modWith(k, f))
  }

  priv pure fn balance (c : RBColor, l : @RBMap<K,V>, k : K, v : @Option<V>, r : @RBMap<K,V>) -> @RBMap<K,V> {
    match (c,l,k,v,r) {
      (Black,@Tree(Red,@Tree(Red,a,xK,xV,b),yK,yV,c),zK,zV,d) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (Black,@Tree(Red,a,xK,xV,@Tree(Red,b,yK,yV,c)),zK,zV,d) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (Black,a,xK,xV,@Tree(Red,@Tree(Red,b,yK,yV,c),zK,zV,d)) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (Black,a,xK,xV,@Tree(Red,b,yK,yV,@Tree(Red,c,zK,zV,d))) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }

  priv pure fn modWith (k : K, f : fn(K, @Option<V>) -> @Option<V>) -> @RBMap<K, V> {
    match self {
      @Leaf => @Tree(Red, self, k, f(k, @None), self),
      @Tree(color, left, key, maybe_value, right) => {
        if (k.lt(&key)) {
          self.balance(color, left.modWith(k, f), key, maybe_value, right)
        } else if (k == key) {
          @Tree(color, left, k, f(key, maybe_value), right)
        } else {
          self.balance(color, left, key, maybe_value, right.modWith(k, f))
        }
      }
    }
  }
}

#[test]
fn test_rb_tree_create() {
  let v1 = RBMap("stevej", 150);
  let v2 = v1.put("thatstacy", 167);

  assert(v2.get("stevej") == @Some(150));
  assert(v2.get("thatstacy") == @Some(167));

  let v3 = v2.delete("stevej");
  assert(v3.get("stevej") == @None);
  assert(v3.get("thatstacy") == @Some(167));
}<commit_msg>added in-order traversal and a test<commit_after>use core::cmp::{Eq, Ord};

pub trait Map<K: Copy Eq Ord, V: Copy> {
  pure fn get(k: K) -> @Option<V>;
  pure fn put(k: K, v: V) -> self;
  pure fn delete(k: K) -> self;
  pure fn traverse(f: fn((&K), (@Option<V>)));
}

enum RBColor {
  Red,
  Black
}

pub enum RBMap<K: Copy Eq Ord, V: Copy> {
  //   color    left         k  value       right
  Tree(RBColor, @RBMap<K,V>, K, @Option<V>, @RBMap<K,V>),
  Leaf
}

pure fn RBMap<K: Copy Eq Ord, V: Copy>(key: K, value: V) -> @RBMap<K, V> {
  @Tree(Red, @Leaf, key, @Some(value), @Leaf)
}

/**
 * A purely functional Red-Black tree.
 *
 * A port of Matt Might's Scala port of Okasaki's RB Trees: http://matt.might.net/articles/implementation-of-immutable-purely-functional-okasaki-red-black-tree-maps-in-scala/RBMap.scala
 * which was itself a port of http://www.ccs.neu.edu/course/cs3500wc/jfp99redblack.pdf
 */
impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> : Map<K, V> {
  pure fn get(k: K) -> @Option<V> {
    match self {
      @Leaf => @None,
      @Tree(_, left, key, maybe_value, right) => {
        if (k.lt(&key)) {
          left.get(k)
        } else if (k.gt(&key)) {
          right.get(k)
        } else {
          maybe_value
        }
      }
    }
  }

  /// Visit all pairs in the map in order.
  pure fn traverse(f: fn((&K), (@Option<V>))) {
    match *self {
      Leaf => (),
      Tree(_, left, key, maybe_value, right) => {
        left.traverse(f);
        f(&key, maybe_value);
        right.traverse(f);
      }
    }
}

  pure fn put(k : K, v : V) -> @RBMap<K, V> {
    self.modifiedWith(k, |m,n| { @Some(v) })
  }

  pure fn delete(k: K) -> @RBMap<K, V> {
    self.modifiedWith(k, |m,n| { @None })
  }

  priv pure fn blacken(n : @RBMap<K, V>) -> @RBMap<K, V> {
    match n {
      @Leaf => n,
      @Tree(_,l,k,v,r) => @Tree(Black,l,k,v,r)
    }
  }

  priv pure fn modifiedWith (k : K, f : fn(K, @Option<V>) -> @Option<V>) -> @RBMap<K, V> {
    self.blacken(self.modWith(k, f))
  }

  priv pure fn balance (c : RBColor, l : @RBMap<K,V>, k : K, v : @Option<V>, r : @RBMap<K,V>) -> @RBMap<K,V> {
    match (c,l,k,v,r) {
      (Black,@Tree(Red,@Tree(Red,a,xK,xV,b),yK,yV,c),zK,zV,d) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (Black,@Tree(Red,a,xK,xV,@Tree(Red,b,yK,yV,c)),zK,zV,d) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (Black,a,xK,xV,@Tree(Red,@Tree(Red,b,yK,yV,c),zK,zV,d)) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (Black,a,xK,xV,@Tree(Red,b,yK,yV,@Tree(Red,c,zK,zV,d))) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }

  priv pure fn modWith (k : K, f : fn(K, @Option<V>) -> @Option<V>) -> @RBMap<K, V> {
    match self {
      @Leaf => @Tree(Red, self, k, f(k, @None), self),
      @Tree(color, left, key, maybe_value, right) => {
        if (k.lt(&key)) {
          self.balance(color, left.modWith(k, f), key, maybe_value, right)
        } else if (k == key) {
          @Tree(color, left, k, f(key, maybe_value), right)
        } else {
          self.balance(color, left, key, maybe_value, right.modWith(k, f))
        }
      }
    }
  }
}

#[test]
fn test_rb_tree_create() {
  let v1 = RBMap("stevej", 150);
  let v2 = v1.put("thatstacy", 167);

  assert(v2.get("stevej") == @Some(150));
  assert(v2.get("thatstacy") == @Some(167));

  let v3 = v2.delete("stevej");
  assert(v3.get("stevej") == @None);
  assert(v3.get("thatstacy") == @Some(167));
}

#[test]
fn test_traverse() {
  let v1 = RBMap(1, 0);
  let v2 = v1.put(4, 0);
  let v3 = v2.put(3, 0);
  let v4 = v3.put(5, 0);
  let v5 = v4.put(2, 0);

  let n = @mut 1;

  fn t(n: @mut int, k: int, _v: Option<int>) {
    assert (*n == k); *n += 1;
  }

  v5.traverse(|x,y| t(n, *x, *y));
}
<|endoftext|>


<commit_before><commit_msg>Finish suggest API<commit_after><|endoftext|>


<commit_before>use std::borrow::Cow;
use std::fs::File;
use std::io::{self, Read};
use std::path::Path;
use toml;
use shellexpand;

#[cfg_attr(rustfmt, rustfmt_skip)]
const CANDIDATES: &'static [&'static str] = &[
    "~/.ghqconfig"
  , "~/.config/ghq/config"
  , ".ghqconfig"
];

#[derive(RustcDecodable)]
pub struct Config {
  pub roots: Vec<String>,
}

impl Default for Config {
  fn default() -> Config {
    Config { roots: vec!["~/.ghq".to_owned()] }
  }
}

impl Config {
  pub fn load() -> io::Result<Config> {
    let mut config: Config = read_file_if_exists(CANDIDATES)
      ?
      .and_then(|ref content| toml::decode_str(content))
      .unwrap_or_default();

    for i in 0..(config.roots.len()) {
      config.roots[i] = shellexpand::full(&config.roots[i]).map(Cow::into_owned).unwrap();
    }

    Ok(config)
  }
}

// Read the content of a file in `paths`
fn read_file_if_exists(paths: &[&str]) -> Result<Option<String>, io::Error> {
  for path in paths {
    // expand the candidate of path.
    let path = shellexpand::full(path).unwrap().into_owned();
    let path = Path::new(&path);

    if path.exists() && path.is_file() {
      let mut content = String::new();
      return File::open(path)
        .and_then(|ref mut file| file.read_to_string(&mut content))
        .and(Ok(Some(content)));
    }
  }
  Ok(None)
}
<commit_msg>refactor<commit_after>use std::borrow::Cow;
use std::env::VarError;
use std::fs::File;
use std::io::{self, Read};
use std::path::PathBuf;
use toml;
use shellexpand::{self, LookupError};

#[cfg_attr(rustfmt, rustfmt_skip)]
const CANDIDATES: &'static [&'static str] = &[
    "~/.ghqconfig"
  , "~/.config/ghq/config"
  , ".ghqconfig"
];

#[derive(RustcDecodable)]
pub struct Config {
  pub roots: Vec<String>,
}

impl Default for Config {
  fn default() -> Config {
    Config { roots: vec!["~/.ghq".to_owned()] }
  }
}

impl Config {
  pub fn load() -> io::Result<Config> {
    let content = read_file_if_exists(CANDIDATES)?;
    let mut config: Config = content.and_then(|s| toml::decode_str(&s)).unwrap_or_default();

    for i in 0..(config.roots.len()) {
      config.roots[i] = expand_full(&config.roots[i]).unwrap();
    }

    Ok(config)
  }
}

fn expand_full(s: &str) -> Result<String, LookupError<VarError>> {
  shellexpand::full(s).map(Cow::into_owned)
}

// Read the content of a file in `paths`
fn read_file_if_exists(paths: &[&str]) -> io::Result<Option<String>> {
  let path = paths.iter()
    .map(|s| expand_full(s).unwrap())
    .map(PathBuf::from)
    .filter(|ref p| p.is_file())
    .next();

  match path {
    Some(path) => {
      let mut content = String::new();
      File::open(path)?.read_to_string(&mut content)?;
      Ok(Some(content))
    }
    None => Ok(None),
  }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
use std::{cmp, result, io};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: io::Error) {
            from()
            cause(err)
            description(err.description())
        }
        Store(err: StorageError) {
            from()
            cause(err)
            description(err.description())
        }
        StepLocalMsg {
            description("raft: cannot step raft local message")
        }
        StepPeerNotFound {
            description("raft: cannot step as peer not found")
        }
    }
}

quick_error! {
    #[derive(Debug, PartialEq)]
    pub enum StorageError {
        Compacted {
            description("log compacted")
        }
        Unavailable {
            description("log unavailable")
        }
        SnapshotOutOfDate {
            description("snapshot out of date")
        }
    }
}

impl cmp::PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        match (self, other) {
            (&Error::StepPeerNotFound, &Error::StepPeerNotFound) => true,
            (&Error::Store(ref e1), &Error::Store(ref e2)) => e1 == e2,
            (&Error::Io(ref e1), &Error::Io(ref e2)) => e1.kind() == e2.kind(),
            (&Error::StepLocalMsg, &Error::StepLocalMsg) => true,
            _ => false,
        }
    }
}

pub type Result<T> = result::Result<T, Error>;

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

    #[test]
    fn test_equal() {
        assert_eq!(Error::StepPeerNotFound, Error::StepPeerNotFound);
        assert!(Error::StepPeerNotFound != Error::Store(StorageError::Compacted));
        assert_eq!(Error::Store(StorageError::Compacted),
                   Error::Store(StorageError::Compacted));
        assert_eq!(Error::StepLocalMsg, Error::StepLocalMsg);
        assert_eq!(Error::from(io::Error::new(io::ErrorKind::Other, "oh no!")),
                   Error::from(io::Error::new(io::ErrorKind::Other, "oh yes!")));
    }
}
<commit_msg>raft: add other error types<commit_after>#![allow(dead_code)]
use std::{cmp, result, io};
use std::error;
use protobuf::error::ProtobufError;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: io::Error) {
            from()
            cause(err)
            description(err.description())
        }
        Store(err: StorageError) {
            from()
            cause(err)
            description(err.description())
        }
        StepLocalMsg {
            description("raft: cannot step raft local message")
        }
        StepPeerNotFound {
            description("raft: cannot step as peer not found")
        }
        ConfigInvalid(desc: String) {
            description(desc)
        }
        Other(err: Box<error::Error + Sync + Send>) {
            cause(err.as_ref())
            description(err.description())
        }
    }
}

impl Error {
    pub fn other<T: error::Error + Sync + Send + 'static>(err: T) -> Error {
        Error::Other(Box::new(err))
    }
}

impl cmp::PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        match (self, other) {
            (&Error::StepPeerNotFound, &Error::StepPeerNotFound) => true,
            (&Error::Store(ref e1), &Error::Store(ref e2)) => e1 == e2,
            (&Error::Io(ref e1), &Error::Io(ref e2)) => e1.kind() == e2.kind(),
            (&Error::StepLocalMsg, &Error::StepLocalMsg) => true,
            (&Error::ConfigInvalid(ref e1), &Error::ConfigInvalid(ref e2)) => e1 == e2,
            _ => false,
        }
    }
}

impl From<ProtobufError> for Error {
    fn from(e: ProtobufError) -> Error {
        Error::other(e)
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum StorageError {
        Compacted {
            description("log compacted")
        }
        Unavailable {
            description("log unavailable")
        }
        SnapshotOutOfDate {
            description("snapshot out of date")
        }
        SnapshotTemporarilyUnavailable {
            description("snapshot is temporarily unavailable")
        }
        Other(err: Box<error::Error + Sync + Send>) {
            cause(err.as_ref())
            description(err.description())
        }
    }
}

impl StorageError {
    pub fn other<T: error::Error + Sync + Send + 'static>(err: T) -> StorageError {
        StorageError::Other(Box::new(err))
    }
}

impl cmp::PartialEq for StorageError {
    fn eq(&self, other: &StorageError) -> bool {
        match (self, other) {
            (&StorageError::Compacted, &StorageError::Compacted) => true,
            (&StorageError::Unavailable, &StorageError::Unavailable) => true,
            (&StorageError::SnapshotOutOfDate,
             &StorageError::SnapshotOutOfDate) => true,
            (&StorageError::SnapshotTemporarilyUnavailable,
             &StorageError::SnapshotTemporarilyUnavailable) => true,
            _ => false,
        }
    }
}

pub type Result<T> = result::Result<T, Error>;

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

    #[test]
    fn test_error_equal() {
        assert_eq!(Error::StepPeerNotFound, Error::StepPeerNotFound);
        assert!(Error::StepPeerNotFound != Error::Store(StorageError::Compacted));
        assert_eq!(Error::Store(StorageError::Compacted),
                   Error::Store(StorageError::Compacted));
        assert_eq!(Error::StepLocalMsg, Error::StepLocalMsg);
        assert_eq!(Error::from(io::Error::new(io::ErrorKind::Other, "oh no!")),
                   Error::from(io::Error::new(io::ErrorKind::Other, "oh yes!")));
    }

    #[test]
    fn test_storage_error_equal() {
        assert_eq!(StorageError::Compacted, StorageError::Compacted);
        assert!(StorageError::Compacted != StorageError::Unavailable);
        assert_eq!(StorageError::Unavailable, StorageError::Unavailable);
        assert_eq!(StorageError::SnapshotOutOfDate,
                   StorageError::SnapshotOutOfDate);
        assert_eq!(StorageError::SnapshotTemporarilyUnavailable,
                   StorageError::SnapshotTemporarilyUnavailable);
        assert!(StorageError::other(Error::StepLocalMsg) != StorageError::Unavailable);
    }
}
<|endoftext|>


<commit_before>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use hyper;
use serde;
use serde_json;

use Version;
use Projects;
use Groups;
use GroupsListing;

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Pagination,

    groups: GroupsListing,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, client: {:?}, pagination: {:?} }}",
                self.scheme, self.domain, self.port, self.client, self.pagination)
    }
}

impl GitLab {

    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port:   port,
            private_token: private_token.to_string(),
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                },
                Err(_) => hyper::Client::new(),
            },
            pagination: Pagination {page: 1, per_page: 20},
            groups: GroupsListing {},
        }
    }

    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", &domain, 80, &private_token)
    }

    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", &domain, 443, &private_token)
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com:443/api/v3/projects?private_token=XXXXXXXXXXXXX&page=1&per_page=20";
    ///
    /// let gl = GitLab::new_https("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("projects"), expected_url);
    /// ```
    pub fn build_url(&self, command: &str) -> String {
        format!("{}://{}:{}/api/v{}/{}?private_token={}&page={}&per_page={}",
                                self.scheme,
                                self.domain,
                                self.port,
                                API_VERSION,
                                command,
                                self.private_token,
                                self.pagination.page,
                                self.pagination.per_page)
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        let url = self.build_url("version");
        // Close connections after each GET.
        let res = self.client.get(&url).header(hyper::header::Connection::close()).send();

        res
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = pagination;
    }

    pub fn get<T>(&self, command: &str) -> Result<T, serde_json::Error>
            where T: serde::Deserialize {

        let url = self.build_url(command);
        let mut res: hyper::client::Response =
                        self.client
                        .get(&url)
                        .header(hyper::header::Connection::close())
                        .send()
                        .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        serde_json::from_str(&body.as_str())
    }

    pub fn version(&self) -> Result<Version, serde_json::Error> {
        self.get("version")
    }

    pub fn groups(&self) -> Result<Groups, serde_json::Error> {
        self.get("groups")
    }

    pub fn projects(&self) -> Result<Projects, serde_json::Error> {
        self.get("projects")
    }

    pub fn listing(&mut self) {

    }
}

/*
#[cfg(test)]
mod tests {

    #[test]
    fn it_works() {
    }
}
*/
<commit_msg>Replace `GitLab::listing()` with `groups_listing()`<commit_after>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use hyper;
use serde;
use serde_json;

use Version;
use Projects;
use Groups;
use GroupsListing;

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Pagination,

    groups: GroupsListing,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, client: {:?}, pagination: {:?} }}",
                self.scheme, self.domain, self.port, self.client, self.pagination)
    }
}

impl GitLab {

    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port:   port,
            private_token: private_token.to_string(),
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                },
                Err(_) => hyper::Client::new(),
            },
            pagination: Pagination {page: 1, per_page: 20},
            groups: GroupsListing {},
        }
    }

    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", &domain, 80, &private_token)
    }

    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", &domain, 443, &private_token)
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com:443/api/v3/projects?private_token=XXXXXXXXXXXXX&page=1&per_page=20";
    ///
    /// let gl = GitLab::new_https("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("projects"), expected_url);
    /// ```
    pub fn build_url(&self, command: &str) -> String {
        format!("{}://{}:{}/api/v{}/{}?private_token={}&page={}&per_page={}",
                                self.scheme,
                                self.domain,
                                self.port,
                                API_VERSION,
                                command,
                                self.private_token,
                                self.pagination.page,
                                self.pagination.per_page)
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        let url = self.build_url("version");
        // Close connections after each GET.
        let res = self.client.get(&url).header(hyper::header::Connection::close()).send();

        res
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = pagination;
    }

    pub fn get<T>(&self, command: &str) -> Result<T, serde_json::Error>
            where T: serde::Deserialize {

        let url = self.build_url(command);
        let mut res: hyper::client::Response =
                        self.client
                        .get(&url)
                        .header(hyper::header::Connection::close())
                        .send()
                        .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        serde_json::from_str(&body.as_str())
    }

    pub fn version(&self) -> Result<Version, serde_json::Error> {
        self.get("version")
    }

    pub fn groups(&self) -> Result<Groups, serde_json::Error> {
        self.get("groups")
    }

    pub fn projects(&self) -> Result<Projects, serde_json::Error> {
        self.get("projects")
    }

    pub fn groups_listing(&mut self) -> GroupsListing {
        GroupsListing { }
    }
}

/*
#[cfg(test)]
mod tests {

    #[test]
    fn it_works() {
    }
}
*/
<|endoftext|>


<commit_before>use num::Zero;
use std::marker::PhantomData;

use failure::{Error, Fail};
use strum_macros::Display;

use super::arch;
use super::arch::Arch;
use super::loaders::pe::PELoader;
use super::loaders::sc::ShellcodeLoader;

#[derive(Debug, Fail)]
pub enum LoaderError {
    #[fail(display = "The given buffer is not supported (arch/plat/file format)")]
    NotSupported,
    #[fail(display = "The given buffer uses a bitness incompatible with the architecture")]
    MismatchedBitness,
}

#[derive(Display, Clone, Copy)]
pub enum FileFormat {
    Raw, // shellcode
    PE,
}

#[derive(Display, Clone, Copy)]
pub enum Platform {
    Windows,
}

#[derive(Debug)]
pub struct Section<A: Arch> {
    pub addr: A::RVA,
    pub buf: Vec<u8>,
    // TODO
    pub perms: u8,
    pub name: String,
}

impl<A: Arch> Section<A> {
    pub fn contains(self: &Section<A>, rva: A::RVA) -> bool {
        if rva < self.addr {
            return false;
        }

        if let Some(max) = arch::rva_add_usize::<A>(self.addr, self.buf.len()) {
            if rva >= max {
                return false;
            }
        } else {
            return false;
        }

        true
    }

    pub fn is_executable(&self) -> bool {
        // TODO
        true
    }
}

pub struct LoadedModule<A: Arch> {
    pub base_address: A::VA,
    pub sections: Vec<Section<A>>,
}

pub trait Loader<A: Arch> {
    /// Fetch the number of bits for a pointer in this architecture.
    fn get_arch(&self) -> u8;
    fn get_plat(&self) -> Platform;
    fn get_file_format(&self) -> FileFormat;

    fn get_name(&self) -> String {
        return format!(
            "{}/{}/{}",
            self.get_plat(),
            self.get_arch(),
            self.get_file_format()
        );
    }

    /// Returns True if this Loader knows how to load the given bytes.
    fn taste(&self, buf: &[u8]) -> bool;

    /// Load the given bytes into a Module.
    fn load(&self, buf: &[u8]) -> Result<LoadedModule<A>, Error>;
}

pub fn default_loaders<A: Arch + 'static + std::fmt::Debug>() -> Vec<Box<dyn Loader<A>>> {
    // we might like these to come from a lazy_static global,
    //  however, then these have to be Sync.
    // I'm not sure if that's a good idea yet.
    let mut loaders: Vec<Box<dyn Loader<A>>> = vec![];
    // the order here matters!
    // the default `load` routine will pick the first matching loader,
    //  so the earlier entries here have higher precedence.

    loaders.push(Box::new(PELoader::<A>::new()));
    loaders.push(Box::new(ShellcodeLoader::<A>::new(Platform::Windows)));

    loaders
}

/// Find the loaders that support loading the given sample.
///
/// The result is an iterator so that the caller can use the first
///  matching result without waiting for all Loaders to taste the bytes.
///
/// Loaders are tasted in the order defined in `default_loaders`.
///
/// Example:
///
/// ```
/// use lancelot::arch::*;
/// use lancelot::loader::*;
///
/// match taste::<Arch32>(b"\xEB\xFE").nth(0) {
///   Some(loader) => assert_eq!(loader.get_name(), "Windows/32/Raw"),
///   None => panic!("no matching loaders"),
/// };
/// ```
pub fn taste<A: Arch + 'static + std::fmt::Debug>(buf: &[u8]) -> impl Iterator<Item = Box<dyn Loader<A>>> {
    default_loaders::<A>()
        .into_iter()
        .filter(move |loader| loader.taste(buf))
}

/// Load the given sample as a 32-bit module using the first matching
///  loader from `default_loaders`.
///
/// Example:
///
/// ```
/// use lancelot::arch::*;
/// use lancelot::loader::*;
///
/// load::<Arch32>(b"\xEB\xFE")
///   .map(|(loader, module)| {
///     assert_eq!(loader.get_name(),       "Windows/32/Raw");
///     assert_eq!(module.base_address,     0x0);
///     assert_eq!(module.sections[0].name, "raw");
///   })
///   .map_err(|e| panic!(e));
/// ```
pub fn load<A: Arch + 'static + std::fmt::Debug>(buf: &[u8]) -> Result<(Box<dyn Loader<A>>, LoadedModule<A>), Error> {
    match taste::<A>(buf).nth(0) {
        Some(loader) => loader.load(buf).map(|module| (loader, module)),
        None => Err(LoaderError::NotSupported.into()),
    }
}
<commit_msg>loader: dbg msg which loader is chosen<commit_after>use num::Zero;
use std::marker::PhantomData;

use failure::{Error, Fail};
use strum_macros::Display;
use log::{debug, info, warn};

use super::arch;
use super::arch::Arch;
use super::loaders::pe::PELoader;
use super::loaders::sc::ShellcodeLoader;

#[derive(Debug, Fail)]
pub enum LoaderError {
    #[fail(display = "The given buffer is not supported (arch/plat/file format)")]
    NotSupported,
    #[fail(display = "The given buffer uses a bitness incompatible with the architecture")]
    MismatchedBitness,
}

#[derive(Display, Clone, Copy)]
pub enum FileFormat {
    Raw, // shellcode
    PE,
}

#[derive(Display, Clone, Copy)]
pub enum Platform {
    Windows,
}

#[derive(Debug)]
pub struct Section<A: Arch> {
    pub addr: A::RVA,
    pub buf: Vec<u8>,
    // TODO
    pub perms: u8,
    pub name: String,
}

impl<A: Arch> Section<A> {
    pub fn contains(self: &Section<A>, rva: A::RVA) -> bool {
        if rva < self.addr {
            return false;
        }

        if let Some(max) = arch::rva_add_usize::<A>(self.addr, self.buf.len()) {
            if rva >= max {
                return false;
            }
        } else {
            return false;
        }

        true
    }

    pub fn is_executable(&self) -> bool {
        // TODO
        true
    }
}

pub struct LoadedModule<A: Arch> {
    pub base_address: A::VA,
    pub sections: Vec<Section<A>>,
}

pub trait Loader<A: Arch> {
    /// Fetch the number of bits for a pointer in this architecture.
    fn get_arch(&self) -> u8;
    fn get_plat(&self) -> Platform;
    fn get_file_format(&self) -> FileFormat;

    fn get_name(&self) -> String {
        return format!(
            "{}/{}/{}",
            self.get_plat(),
            self.get_arch(),
            self.get_file_format()
        );
    }

    /// Returns True if this Loader knows how to load the given bytes.
    fn taste(&self, buf: &[u8]) -> bool;

    /// Load the given bytes into a Module.
    fn load(&self, buf: &[u8]) -> Result<LoadedModule<A>, Error>;
}

pub fn default_loaders<A: Arch + 'static + std::fmt::Debug>() -> Vec<Box<dyn Loader<A>>> {
    // we might like these to come from a lazy_static global,
    //  however, then these have to be Sync.
    // I'm not sure if that's a good idea yet.
    let mut loaders: Vec<Box<dyn Loader<A>>> = vec![];
    // the order here matters!
    // the default `load` routine will pick the first matching loader,
    //  so the earlier entries here have higher precedence.

    loaders.push(Box::new(PELoader::<A>::new()));
    loaders.push(Box::new(ShellcodeLoader::<A>::new(Platform::Windows)));

    loaders
}

/// Find the loaders that support loading the given sample.
///
/// The result is an iterator so that the caller can use the first
///  matching result without waiting for all Loaders to taste the bytes.
///
/// Loaders are tasted in the order defined in `default_loaders`.
///
/// Example:
///
/// ```
/// use lancelot::arch::*;
/// use lancelot::loader::*;
///
/// match taste::<Arch32>(b"\xEB\xFE").nth(0) {
///   Some(loader) => assert_eq!(loader.get_name(), "Windows/32/Raw"),
///   None => panic!("no matching loaders"),
/// };
/// ```
pub fn taste<A: Arch + 'static + std::fmt::Debug>(buf: &[u8]) -> impl Iterator<Item = Box<dyn Loader<A>>> {
    default_loaders::<A>()
        .into_iter()
        .filter(move |loader| loader.taste(buf))
}

/// Load the given sample as a 32-bit module using the first matching
///  loader from `default_loaders`.
///
/// Example:
///
/// ```
/// use lancelot::arch::*;
/// use lancelot::loader::*;
///
/// load::<Arch32>(b"\xEB\xFE")
///   .map(|(loader, module)| {
///     assert_eq!(loader.get_name(),       "Windows/32/Raw");
///     assert_eq!(module.base_address,     0x0);
///     assert_eq!(module.sections[0].name, "raw");
///   })
///   .map_err(|e| panic!(e));
/// ```
pub fn load<A: Arch + 'static + std::fmt::Debug>(buf: &[u8]) -> Result<(Box<dyn Loader<A>>, LoadedModule<A>), Error> {
    match taste::<A>(buf).nth(0) {
        Some(loader) => {
            info!("auto-detected loader: {}", loader.get_name());
            loader.load(buf).map(|module| (loader, module))
        },
        None => Err(LoaderError::NotSupported.into()),
    }
}
<|endoftext|>


<commit_before>/**
Registers a selector, returning a `Sel`.

# Example
```
# #[macro_use] extern crate objc;
# fn main() {
let sel = sel!(description);
let sel = sel!(setObject:forKey:);
# }
```
*/
#[macro_export]
macro_rules! sel {
    // Declare a function to hide unsafety, otherwise we can trigger the
    // unused_unsafe lint; see rust-lang/rust#8472
    ($name:ident) => ({
        #[inline(always)]
        fn register_sel(name_with_nul: &str) -> $crate::runtime::Sel {
            let ptr = name_with_nul.as_ptr() as *const _;
            unsafe { $crate::runtime::sel_registerName(ptr) }
        }
        register_sel(concat!(stringify!($name), '\0'))
    });
    ($($name:ident :)+) => ({
        #[inline(always)]
        fn register_sel(name_with_nul: &str) -> $crate::runtime::Sel {
            let ptr = name_with_nul.as_ptr() as *const _;
            unsafe { $crate::runtime::sel_registerName(ptr) }
        }
        register_sel(concat!($(stringify!($name), ':'),+, '\0'))
    });
}

/**
Sends a message to an object.

The first argument can be any type that dereferences to a type that implements
`Message`, like a reference, pointer, or an `Id`.
The syntax is similar to the message syntax in Objective-C.
Variadic arguments are not currently supported.

# Example
``` no_run
# #[macro_use] extern crate objc;
# use objc::runtime::Object;
# fn main() {
# unsafe {
let obj: *mut Object;
# let obj: *mut Object = 0 as *mut Object;
let description: *const Object = msg_send![obj, description];
let _: () = msg_send![obj, setArg1:1 arg2:2];
# }
# }
```
*/
#[macro_export]
macro_rules! msg_send {
    (super($obj:expr, $superclass:expr), $name:ident) => ({
        let sel = sel!($name);
        match $crate::__send_super_message(&*$obj, $superclass, sel, ()) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
    (super($obj:expr, $superclass:expr), $($name:ident : $arg:expr)+) => ({
        let sel = sel!($($name:)+);
        match $crate::__send_super_message(&*$obj, $superclass, sel, ($($arg,)*)) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
    ($obj:expr, $name:ident) => ({
        let sel = sel!($name);
        match $crate::__send_message(&*$obj, sel, ()) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
    ($obj:expr, $($name:ident : $arg:expr)+) => ({
        let sel = sel!($($name:)+);
        match $crate::__send_message(&*$obj, sel, ($($arg,)*)) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
}

macro_rules! encode {
    () => ("");
    (i8 $($x:tt)*) => (concat!("c", encode!($($x)*)));
    (i16 $($x:tt)*) => (concat!("s", encode!($($x)*)));
    (i32 $($x:tt)*) => (concat!("i", encode!($($x)*)));
    (i64 $($x:tt)*) => (concat!("q", encode!($($x)*)));
    (u8 $($x:tt)*) => (concat!("C", encode!($($x)*)));
    (u16 $($x:tt)*) => (concat!("S", encode!($($x)*)));
    (u32 $($x:tt)*) => (concat!("I", encode!($($x)*)));
    (u64 $($x:tt)*) => (concat!("Q", encode!($($x)*)));
    (f32 $($x:tt)*) => (concat!("f", encode!($($x)*)));
    (f64 $($x:tt)*) => (concat!("d", encode!($($x)*)));
    (bool $($x:tt)*) => (concat!("B", encode!($($x)*)));
    (Sel $($x:tt)*) => (concat!(":", encode!($($x)*)));
    (struct $i:ident {$($x:tt)+}) => (
        concat!('{', stringify!($i), '=', encode!($($x)*), '}')
    );
    // Just eat a leading comma and continue
    (, $($x:tt)*) => (encode!($($x)*));
}
<commit_msg>Remove the unused encode! macro.<commit_after>/**
Registers a selector, returning a `Sel`.

# Example
```
# #[macro_use] extern crate objc;
# fn main() {
let sel = sel!(description);
let sel = sel!(setObject:forKey:);
# }
```
*/
#[macro_export]
macro_rules! sel {
    // Declare a function to hide unsafety, otherwise we can trigger the
    // unused_unsafe lint; see rust-lang/rust#8472
    ($name:ident) => ({
        #[inline(always)]
        fn register_sel(name_with_nul: &str) -> $crate::runtime::Sel {
            let ptr = name_with_nul.as_ptr() as *const _;
            unsafe { $crate::runtime::sel_registerName(ptr) }
        }
        register_sel(concat!(stringify!($name), '\0'))
    });
    ($($name:ident :)+) => ({
        #[inline(always)]
        fn register_sel(name_with_nul: &str) -> $crate::runtime::Sel {
            let ptr = name_with_nul.as_ptr() as *const _;
            unsafe { $crate::runtime::sel_registerName(ptr) }
        }
        register_sel(concat!($(stringify!($name), ':'),+, '\0'))
    });
}

/**
Sends a message to an object.

The first argument can be any type that dereferences to a type that implements
`Message`, like a reference, pointer, or an `Id`.
The syntax is similar to the message syntax in Objective-C.
Variadic arguments are not currently supported.

# Example
``` no_run
# #[macro_use] extern crate objc;
# use objc::runtime::Object;
# fn main() {
# unsafe {
let obj: *mut Object;
# let obj: *mut Object = 0 as *mut Object;
let description: *const Object = msg_send![obj, description];
let _: () = msg_send![obj, setArg1:1 arg2:2];
# }
# }
```
*/
#[macro_export]
macro_rules! msg_send {
    (super($obj:expr, $superclass:expr), $name:ident) => ({
        let sel = sel!($name);
        match $crate::__send_super_message(&*$obj, $superclass, sel, ()) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
    (super($obj:expr, $superclass:expr), $($name:ident : $arg:expr)+) => ({
        let sel = sel!($($name:)+);
        match $crate::__send_super_message(&*$obj, $superclass, sel, ($($arg,)*)) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
    ($obj:expr, $name:ident) => ({
        let sel = sel!($name);
        match $crate::__send_message(&*$obj, sel, ()) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
    ($obj:expr, $($name:ident : $arg:expr)+) => ({
        let sel = sel!($($name:)+);
        match $crate::__send_message(&*$obj, sel, ($($arg,)*)) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
}
<|endoftext|>


<commit_before>//use Tensor;
//use tensor;

/// Macro for creating vectors and matrices.
///
/// To use this macro, import Numeric as follows:
///
/// ```text
/// #[macro_use(tensor)]
/// extern crate numeric;
/// ```
///
/// # Examples
///
/// 1D tensor (vector):
///
/// ```
/// # #[macro_use] extern crate numeric; fn main() {
/// let x = tensor![1.0, 2.0, 3.0];
/// # assert!(x == numeric::Tensor::new(vec![1.0, 2.0, 3.0]));
/// # }
/// ```
///
/// 2D tensor (matrix):
///
/// ```
/// # #[macro_use] extern crate numeric; use numeric::tensor; fn main() {
/// let x = tensor![1, 0; 3, 2; 5, 4];
/// # assert!(x == numeric::Tensor::new(vec![1, 0, 3, 2, 5, 4]).reshape(&[3, 2]));
/// # }
/// ```
///
/// 1D tensor filled with a single value:
///
/// ```
/// # #[macro_use] extern crate numeric; use numeric::tensor; fn main() {
/// let x = tensor![2.0; 5];
/// # assert!(x == numeric::Tensor::new(vec![2.0, 2.0, 2.0, 2.0, 2.0]));
/// # }
/// ```
#[macro_export]
macro_rules! tensor {
    ($elem:expr; $n:expr) => (
        numeric::Tensor::filled(&[$n], $elem)
    );
    ($($x:expr),*) => (
        numeric::Tensor::new(vec![$($x),*])
    );
    ($($($x:expr),*);*) => ({
        let mut v = Vec::new();
        let mut n = 0;
        $(
            n += 1;
            $(v.push($x);)*
        )*
        numeric::Tensor::new(v).reshape(&[n, -1])
    });
}
<commit_msg>Make tensor! independent of the crate’s name<commit_after>//use Tensor;
//use tensor;

/// Macro for creating vectors and matrices.
///
/// To use this macro, import Numeric as follows:
///
/// ```text
/// #[macro_use(tensor)]
/// extern crate numeric;
/// ```
///
/// # Examples
///
/// 1D tensor (vector):
///
/// ```
/// # #[macro_use] extern crate numeric; fn main() {
/// let x = tensor![1.0, 2.0, 3.0];
/// # assert!(x == numeric::Tensor::new(vec![1.0, 2.0, 3.0]));
/// # }
/// ```
///
/// 2D tensor (matrix):
///
/// ```
/// # #[macro_use] extern crate numeric; use numeric::tensor; fn main() {
/// let x = tensor![1, 0; 3, 2; 5, 4];
/// # assert!(x == numeric::Tensor::new(vec![1, 0, 3, 2, 5, 4]).reshape(&[3, 2]));
/// # }
/// ```
///
/// 1D tensor filled with a single value:
///
/// ```
/// # #[macro_use] extern crate numeric; use numeric::tensor; fn main() {
/// let x = tensor![2.0; 5];
/// # assert!(x == numeric::Tensor::new(vec![2.0, 2.0, 2.0, 2.0, 2.0]));
/// # }
/// ```
#[macro_export]
macro_rules! tensor {
    ($elem:expr; $n:expr) => (
        $crate::Tensor::filled(&[$n], $elem)
    );
    ($($x:expr),*) => (
        $crate::Tensor::new(vec![$($x),*])
    );
    ($($($x:expr),*);*) => ({
        let mut v = Vec::new();
        let mut n = 0;
        $(
            n += 1;
            $(v.push($x);)*
        )*
        $crate::Tensor::new(v).reshape(&[n, -1])
    });
}

#[cfg(test)]
mod tests {
    use Tensor;

    #[test]
    fn tensor() {
        let x = Tensor::new(vec![1, 2, 3, 4, 5, 6]).reshape(&[3, 2]);
        let y = tensor![1, 2; 3, 4; 5, 6];
        assert!(x == y);
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix types<commit_after><|endoftext|>


<commit_before>use errors::*;
use chrono::prelude::Utc;
use chrono::DateTime;
use nom::{is_digit, space, IResult};
use token::Token;
use die::Die;
use std::str;

#[derive(Debug, Deserialize, Serialize)]
pub struct Output {
    /// The original input
    pub input: String,

    /// Errors, if any
    pub errors: Vec<ErrorOutput>,

    /// Timestamp
    pub executed: DateTime<Utc>,

    /// Time to execute final output
    pub execution_time: i64,

    /// Chat messages to be sent
    pub messages: Vec<String>,

    /// Dice rolls
    pub rolls: Vec<Die>,

    /// Tokens
    pub tokens: Vec<Token>,

    /// API Version
    pub version: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ErrorOutput {
    /// Type of error
    error: String,

    /// Message
    message: String
}

// Read "#" and take until the first whitespace
named!(take_macro_name <&str>, do_parse!(
    tag!("#") >>
    name: map_res!(
        is_not!(" \t\r\n"),
        str::from_utf8
    ) >>
    (name)
));

// Read a command
named!(read_command <Vec<&[u8]>>, many0!(do_parse!(
    alt!(tag!("!roll") | tag!("!r")) >>
    command: take_until!(" ") >>
    (command)
)));

/// Parses TTML and executes on-the-fly
// pub fn parse_ttml(input: &str) -> IResult<&[u8], &str> {
    // // parse_macro(input.as_bytes())
// }

#[test]
fn test_take_macro_name() {
    // macro names can be alphanumeric
    let cmd1 = take_macro_name(b"#test !say \"Hello\"");
    let res1 = IResult::Done(&b" !say \"Hello\""[..], "test");
    assert_eq!(cmd1, res1);

    // macro names can have dashes
    let cmd2 = take_macro_name(b"#test-macro !say \"Hello\"");
    let res2 = IResult::Done(&b" !say \"Hello\""[..], "test-macro");
    assert_eq!(cmd2, res2);

    // macro names can have underscores
    let cmd3 = take_macro_name(b"#test_macro !say \"Hello\"");
    let res3 = IResult::Done(&b" !say \"Hello\""[..], "test_macro");
    assert_eq!(cmd3, res3);

    // macro names can start with numbers
    let cmd4 = take_macro_name(b"#123abcZZZ !say \"Hello\"");
    let res4 = IResult::Done(&b" !say \"Hello\""[..], "123abcZZZ");
    assert_eq!(cmd4, res4);

    // macro names can start with capital letters
    let cmd5 = take_macro_name(b"#Zxy123 !say \"Hello\"");
    let res5 = IResult::Done(&b" !say \"Hello\""[..], "Zxy123");
    assert_eq!(cmd5, res5);

    // parse only the first macro when multiple macros in the same line
    let cmd5 = take_macro_name(b"#test !say \"Hello\" #multiple !roll 1d20");
    let res5 = IResult::Done(&b" !say \"Hello\" #multiple !roll 1d20"[..], "test");
    assert_eq!(cmd5, res5);
}

#[test]
fn test_read_command() {
    let cmd = read_command(b"!roll 1d20");
    println!("cmd {}", String::from_utf8_lossy(cmd.unwrap().0));
}
<commit_msg>WIP parse command name<commit_after>use errors::*;
use chrono::prelude::Utc;
use chrono::DateTime;
use nom::{is_digit, space, IResult};
use token::Token;
use die::Die;
use std::str;

#[derive(Debug, Deserialize, Serialize)]
pub struct Output {
    /// The original input
    pub input: String,

    /// Errors, if any
    pub errors: Vec<ErrorOutput>,

    /// Timestamp
    pub executed: DateTime<Utc>,

    /// Time to execute final output
    pub execution_time: i64,

    /// Chat messages to be sent
    pub messages: Vec<String>,

    /// Dice rolls
    pub rolls: Vec<Die>,

    /// Tokens
    pub tokens: Vec<Token>,

    /// API Version
    pub version: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ErrorOutput {
    /// Type of error
    error: String,

    /// Message
    message: String
}

// Read "#" and take until the first whitespace
named!(take_macro_name <&str>, do_parse!(
    tag!("#") >>
    name: map_res!(
        is_not!(" \t\r\n"),
        str::from_utf8
    ) >>
    (name)
));

// Read a command
named!(take_command_name <&[u8]>, do_parse!(
    command: alt!(
        tag!("!roll") | tag!("!r") |
        tag!("!say") | tag!("!s") |
        tag!("!whisper") | tag!("!w")
    ) >>
    value: take_until!(" ") >>
    (command)
));

/// Parses TTML and executes on-the-fly
// pub fn parse_ttml(input: &str) -> IResult<&[u8], &str> {
    // // parse_macro(input.as_bytes())
// }

// @todo - make the parsers above public functions so we can test them from the tests/ dir
#[test]
fn test_take_macro_name() {
    // macro names can be alphanumeric
    let cmd1 = take_macro_name(b"#test !say \"Hello\"");
    let res1 = IResult::Done(&b" !say \"Hello\""[..], "test");
    assert_eq!(cmd1, res1);

    // macro names can have dashes
    let cmd2 = take_macro_name(b"#test-macro !say \"Hello\"");
    let res2 = IResult::Done(&b" !say \"Hello\""[..], "test-macro");
    assert_eq!(cmd2, res2);

    // macro names can have underscores
    let cmd3 = take_macro_name(b"#test_macro !say \"Hello\"");
    let res3 = IResult::Done(&b" !say \"Hello\""[..], "test_macro");
    assert_eq!(cmd3, res3);

    // macro names can start with numbers
    let cmd4 = take_macro_name(b"#123abcZZZ !say \"Hello\"");
    let res4 = IResult::Done(&b" !say \"Hello\""[..], "123abcZZZ");
    assert_eq!(cmd4, res4);

    // macro names can start with capital letters
    let cmd5 = take_macro_name(b"#Zxy123 !say \"Hello\"");
    let res5 = IResult::Done(&b" !say \"Hello\""[..], "Zxy123");
    assert_eq!(cmd5, res5);

    // parse only the first macro when multiple macros in the same line
    let cmd5 = take_macro_name(b"#test !say \"Hello\" #multiple !roll 1d20");
    let res5 = IResult::Done(&b" !say \"Hello\" #multiple !roll 1d20"[..], "test");
    assert_eq!(cmd5, res5);
}

#[test]
fn test_take_command_name_roll() {
    let (rest, cmd) = take_command_name(b"!roll 1d20").unwrap();
    assert_eq!(cmd, b"!roll");
    assert_eq!(rest, b" 1d20");

    let (rest, cmd) = take_command_name(b"!r 1d20").unwrap();
    assert_eq!(cmd, b"!r");
    assert_eq!(rest, b" 1d20");
}

#[test]
fn test_take_command_name_say() {
    let (rest, cmd) = take_command_name(b"!say \"Hello\"").unwrap();
    assert_eq!(cmd, b"!say");
    assert_eq!(rest, b" \"Hello\"");

    let (rest, cmd) = take_command_name(b"!s \"Hello\"").unwrap();
    assert_eq!(cmd, b"!s");
    assert_eq!(rest, b" \"Hello\"");
}

#[test]
fn test_take_command_name_whisper() {
    let (rest, cmd) = take_command_name(b"!whisper $gm \"Hello\"").unwrap();
    assert_eq!(cmd, b"!whisper");
    assert_eq!(rest, b" $gm \"Hello\"");

    let (rest, cmd) = take_command_name(b"!w $gm \"Hello\"").unwrap();
    assert_eq!(cmd, b"!w");
    assert_eq!(rest, b" $gm \"Hello\"");
}
<|endoftext|>


<commit_before><commit_msg>Fix AND in conclusions<commit_after><|endoftext|>


<commit_before><commit_msg>Add parse and render function<commit_after><|endoftext|>


<commit_before><commit_msg>Added print to unit tests to increase coverage<commit_after><|endoftext|>


<commit_before><commit_msg>Return a parser error on integer overflows (fixes #9)<commit_after><|endoftext|>