<commit_before>extern crate ktensor as k;

fn relu_layer_f64<'a>(layer_number: usize, x: &'a k::Graph<f64>, w: &'a k::Graph<f64>, b: &'a k::Graph<f64>) -> (k::Node<'a, f64>, k::Node<'a, f64>, k::Node<'a, f64>) {
    let dot = k::op::dot::<f64>(format!("layer_{}_dot", layer_number), x, w);
    let add = k::op::add::<f64>(format!("layer_{}_add", layer_number), &dot, b);
    let relu = k::op::relu_f64(format!("layer_{}_relu", layer_number), &add);
    (dot, add, relu)
}

#[test]
fn linear_regression() {
    // Variables
    let input_x = k::Variable::new("input_x".to_string(), k::Vec2(1, 2));
    let target_y = k::Variable::new("target_y".to_string(), k::Vec2(1, 2));

    // Initialize
    let mut variable_context = k::Context::<f64>::with_capacity(2);
    k::variable::init_f64(vec![&input_x, &target_y], &mut variable_context);

    // States
    let weight_w = k::State::new("weight_w".to_string(), k::Vec2(2, 2));
    let weight_b = k::State::new("weight_b".to_string(), k::Vec2(1, 2));

    // Graph
    let mut states = Vec::<k::State>::with_capacity(2 * 2);
    let mut graphs = Vec::<k::Node<f64>>::with_capacity(3 * 2);
    let mut graph_head: &k::Graph<f64> = &input_x;

    for i in 0..2 {
        let w = k::State::new(format!("weight_w_{}", i), k::Vec2(2, 2));
        let b = k::State::new(format!("weight_b_{}", i), k::Vec2(1, 2));
        let (dot, add, relu) = relu_layer_f64(i, graph_head, &w, &b);
        graph_head = &relu;
        graphs.push(dot);
        graphs.push(add);
        graphs.push(relu);
        states.push(w);
        states.push(b);
    }

    let mut state_context = k::Context::<f64>::with_capacity(2);
    k::state::init_f64(&states, &mut state_context);
    let softmax = k::op::softmax_f64("softmax".to_string(), graph_head);
    let xentropy = k::cost::softmax_cross_entropy_f64("xentropy".to_string(), &softmax, &target_y);

    // Training
    let mut history = k::Context::<f64>::with_capacity(6);
    let print_rate = 4096;

    let training_set = vec![
        (k::Tensor::from_vec(k::Vec2(1, 2), vec![0.0, 0.0]), k::Tensor::from_vec(k::Vec2(1, 2), vec![0.0, 1.0])),
        (k::Tensor::from_vec(k::Vec2(1, 2), vec![0.0, 1.0]), k::Tensor::from_vec(k::Vec2(1, 2), vec![1.0, 0.0])),
        (k::Tensor::from_vec(k::Vec2(1, 2), vec![1.0, 0.0]), k::Tensor::from_vec(k::Vec2(1, 2), vec![1.0, 0.0])),
        (k::Tensor::from_vec(k::Vec2(1, 2), vec![1.0, 1.0]), k::Tensor::from_vec(k::Vec2(1, 2), vec![0.0, 1.0])),
    ];

    for i in 0..256 {
        // init batch

        k::train(&xentropy, &mut state_context, &variable_context, &mut history, &0.001);
        if i % print_rate == 0 {

        }
    }
}
<commit_msg>error borrow in linreg<commit_after>extern crate ktensor as k;

#[test]
fn linear_regression() {
    // Variables
    let input_x = k::Variable::new("input_x".to_string(), k::Vec2(1, 2));
    let target_y = k::Variable::new("target_y".to_string(), k::Vec2(1, 2));

    // Initialize
    let mut variable_context = k::Context::<f64>::with_capacity(2);
    k::variable::init_f64(vec![&input_x, &target_y], &mut variable_context);

    // States
    let weight_w = k::State::new("weight_w".to_string(), k::Vec2(2, 2));
    let weight_b = k::State::new("weight_b".to_string(), k::Vec2(1, 2));

    // Graph
    let layers: usize = 2;
    let mut states = Vec::<k::State>::with_capacity(2 * layers);
    let mut graphs = Vec::<k::Node<f64>>::with_capacity(3 * layers);
    let mut graph_head: &k::Graph<f64> = &input_x;

    for i in 0..layers {
        let s = states.len();
        let g = graphs.len();

        states.push(k::State::new(format!("weight_w_{}", i), k::Vec2(2, 2)));
        states.push(k::State::new(format!("weight_b_{}", i), k::Vec2(1, 2)));

        graphs.push(k::op::dot::<f64>(format!("layer_{}_dot", i), graph_head, &states[s + 0]));
        graphs.push(k::op::add::<f64>(format!("layer_{}_add", i), &graphs[g + 0], &states[s + 1]));
        graphs.push(k::op::relu_f64(format!("layer_{}_relu", i), &graphs[g + 1]));

        graph_head = &graphs[g + 2];
    }

    let mut state_context = k::Context::<f64>::with_capacity(2);
    k::state::init_f64(&states, &mut state_context);
    let softmax = k::op::softmax_f64("softmax".to_string(), graph_head);
    let xentropy = k::cost::softmax_cross_entropy_f64("xentropy".to_string(), &softmax, &target_y);

    // Training
    let mut history = k::Context::<f64>::with_capacity(6);
    let print_rate = 4096;

    let training_set = vec![
        (k::Tensor::from_vec(k::Vec2(1, 2), vec![0.0, 0.0]), k::Tensor::from_vec(k::Vec2(1, 2), vec![0.0, 1.0])),
        (k::Tensor::from_vec(k::Vec2(1, 2), vec![0.0, 1.0]), k::Tensor::from_vec(k::Vec2(1, 2), vec![1.0, 0.0])),
        (k::Tensor::from_vec(k::Vec2(1, 2), vec![1.0, 0.0]), k::Tensor::from_vec(k::Vec2(1, 2), vec![1.0, 0.0])),
        (k::Tensor::from_vec(k::Vec2(1, 2), vec![1.0, 1.0]), k::Tensor::from_vec(k::Vec2(1, 2), vec![0.0, 1.0])),
    ];

    for i in 0..256 {
        // init batch

        k::train(&xentropy, &mut state_context, &variable_context, &mut history, &0.001);
        if i % print_rate == 0 {

        }
    }
}
<|endoftext|>


<commit_before>/*
Module: run

Process spawning
*/
import str::sbuf;

export program;
export run_program;
export start_program;
export program_output;
export spawn_process;
export waitpid;

native "c-stack-cdecl" mod rustrt {
    fn rust_run_program(argv: *sbuf, in_fd: int, out_fd: int, err_fd: int) ->
       int;
}

/* Section: Types */

/*
Resource: program_res

A resource that manages the destruction of a <program> object

program_res ensures that the destroy method is called on a
program object in order to close open file descriptors.
*/
resource program_res(p: program) { p.destroy(); }

/*
Obj: program

An object representing a child process
*/
type program = obj {
    /*
    Method: get_id

    Returns the process id of the program
    */
    fn get_id() -> int;

    /*
    Method: input

    Returns an io::writer that can be used to write to stdin
    */
    fn input() -> io::writer;

    /*
    Method: output

    Returns an io::reader that can be used to read from stdout
    */
    fn output() -> io::reader;

    /*
    Method: err

    Returns an io::reader that can be used to read from stderr
    */
    fn err() -> io::reader;

    /*
    Method: close_input

    Closes the handle to the child processes standard input
    */
    fn close_input();

    /*
    Method: finish

    Waits for the child process to terminate. Closes the handle
    to stdin if necessary.
    */
    fn finish() -> int;

    /*
    Method: destroy

    Closes open handles
    */
    fn destroy();
};

/* Section: Operations */

fn arg_vec(prog: str, args: [@str]) -> [sbuf] {
    let argptrs = str::as_buf(prog, {|buf| [buf] });
    for arg in args { argptrs += str::as_buf(*arg, {|buf| [buf] }); }
    // FIXME: ptr::null instead of cast
    argptrs += [unsafe {unsafe::reinterpret_cast(0)}];
    ret argptrs;
}

/*
Function: spawn_process

Run a program, providing stdin, stdout and stderr handles

Parameters:

prog - The path to an executable
args - Vector of arguments to pass to the child process
in_fd - A file descriptor for the child to use as std input
out_fd - A file descriptor for the child to use as std output
err_fd - A file descriptor for the child to use as std error

Returns:

The process id of the spawned process
*/
fn spawn_process(prog: str, args: [str], in_fd: int, out_fd: int, err_fd: int)
   -> int unsafe {
    // Note: we have to hold on to these vector references while we hold a
    // pointer to their buffers
    let prog = prog;
    let args = vec::map({|arg| @arg }, args);
    let argv = arg_vec(prog, args);
    let pid =
        rustrt::rust_run_program(vec::unsafe::to_ptr(argv), in_fd, out_fd,
                                 err_fd);
    ret pid;
}

/*
Function: run_program

Spawns a process and waits for it to terminate

Parameters:

prog - The path to an executable
args - Vector of arguments to pass to the child process

Returns:

The process id
*/
fn run_program(prog: str, args: [str]) -> int {
    ret waitpid(spawn_process(prog, args, 0, 0, 0));
}

/*
Function: start_program

Spawns a process and returns a boxed <program_res>

The returned value is a boxed resource containing a <program> object that can
be used for sending and recieving data over the standard file descriptors.
The resource will ensure that file descriptors are closed properly.

Parameters:

prog - The path to an executable
args - Vector of arguments to pass to the child process

Returns:

A boxed resource of <program>
*/
fn start_program(prog: str, args: [str]) -> @program_res {
    let pipe_input = os::pipe();
    let pipe_output = os::pipe();
    let pipe_err = os::pipe();
    let pid =
        spawn_process(prog, args, pipe_input.in, pipe_output.out,
                      pipe_err.out);

    if pid == -1 { fail; }
    os::libc::close(pipe_input.in);
    os::libc::close(pipe_output.out);
    os::libc::close(pipe_err.out);
    obj new_program(pid: int,
                    mutable in_fd: int,
                    out_file: os::libc::FILE,
                    err_file: os::libc::FILE,
                    mutable finished: bool) {
        fn get_id() -> int { ret pid; }
        fn input() -> io::writer {
            ret io::new_writer(io::fd_buf_writer(in_fd, option::none));
        }
        fn output() -> io::reader {
            ret io::new_reader(io::FILE_buf_reader(out_file, option::none));
        }
        fn err() -> io::reader {
            ret io::new_reader(io::FILE_buf_reader(err_file, option::none));
        }
        fn close_input() {
            let invalid_fd = -1;
            if in_fd != invalid_fd {
                os::libc::close(in_fd);
                in_fd = invalid_fd;
            }
        }
        fn finish() -> int {
            if finished { ret 0; }
            finished = true;
            self.close_input();
            ret waitpid(pid);
        }
        fn destroy() {
            self.finish();
            os::libc::fclose(out_file);
            os::libc::fclose(err_file);
        }
    }
    ret @program_res(new_program(pid, pipe_input.out,
                                 os::fd_FILE(pipe_output.in),
                                 os::fd_FILE(pipe_err.in), false));
}

fn read_all(rd: io::reader) -> str {
    let buf = "";
    while !rd.eof() {
        let bytes = rd.read_bytes(4096u);
        buf += str::unsafe_from_bytes(bytes);
    }
    ret buf;
}

/*
Function: program_output

Spawns a process, waits for it to exit, and returns the exit code, and
contents of stdout and stderr.

Parameters:

prog - The path to an executable
args - Vector of arguments to pass to the child process

Returns:

A record, {status: int, out: str, err: str} containing the exit code,
the contents of stdout and the contents of stderr.
*/
fn program_output(prog: str, args: [str]) ->
   {status: int, out: str, err: str} {
    let pr = start_program(prog, args);
    pr.close_input();
    let out = read_all(pr.output());
    let err = read_all(pr.err());
    ret {status: pr.finish(), out: out, err: err};
}

/*
Function: waitpid

Waits for a process to exit and returns the exit code
*/
fn waitpid(pid: int) -> int {
    ret waitpid_os(pid);

    #[cfg(target_os = "win32")]
    fn waitpid_os(pid: int) -> int {
        os::waitpid(pid)
    }

    #[cfg(target_os = "linux")]
    #[cfg(target_os = "macos")]
    fn waitpid_os(pid: int) -> int {
        #[cfg(target_os = "linux")]
        fn WIFEXITED(status: int) -> bool {
            (status & 0xff) == 0
        }

        #[cfg(target_os = "macos")]
        fn WIFEXITED(status: int) -> bool {
            (status & 0x7f) == 0
        }

        #[cfg(target_os = "linux")]
        fn WEXITSTATUS(status: int) -> int {
            (status >> 8) & 0xff
        }

        #[cfg(target_os = "macos")]
        fn WEXITSTATUS(status: int) -> int {
            status >> 8
        }

        let status = os::waitpid(pid);
        ret if WIFEXITED(status) {
            WEXITSTATUS(status)
        } else {
            1
        };
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>stdlib: Replace an unsafe cast with ptr::null<commit_after>/*
Module: run

Process spawning
*/
import str::sbuf;

export program;
export run_program;
export start_program;
export program_output;
export spawn_process;
export waitpid;

native "c-stack-cdecl" mod rustrt {
    fn rust_run_program(argv: *sbuf, in_fd: int, out_fd: int, err_fd: int) ->
       int;
}

/* Section: Types */

/*
Resource: program_res

A resource that manages the destruction of a <program> object

program_res ensures that the destroy method is called on a
program object in order to close open file descriptors.
*/
resource program_res(p: program) { p.destroy(); }

/*
Obj: program

An object representing a child process
*/
type program = obj {
    /*
    Method: get_id

    Returns the process id of the program
    */
    fn get_id() -> int;

    /*
    Method: input

    Returns an io::writer that can be used to write to stdin
    */
    fn input() -> io::writer;

    /*
    Method: output

    Returns an io::reader that can be used to read from stdout
    */
    fn output() -> io::reader;

    /*
    Method: err

    Returns an io::reader that can be used to read from stderr
    */
    fn err() -> io::reader;

    /*
    Method: close_input

    Closes the handle to the child processes standard input
    */
    fn close_input();

    /*
    Method: finish

    Waits for the child process to terminate. Closes the handle
    to stdin if necessary.
    */
    fn finish() -> int;

    /*
    Method: destroy

    Closes open handles
    */
    fn destroy();
};

/* Section: Operations */

fn arg_vec(prog: str, args: [@str]) -> [sbuf] {
    let argptrs = str::as_buf(prog, {|buf| [buf] });
    for arg in args { argptrs += str::as_buf(*arg, {|buf| [buf] }); }
    argptrs += [ptr::null()];
    ret argptrs;
}

/*
Function: spawn_process

Run a program, providing stdin, stdout and stderr handles

Parameters:

prog - The path to an executable
args - Vector of arguments to pass to the child process
in_fd - A file descriptor for the child to use as std input
out_fd - A file descriptor for the child to use as std output
err_fd - A file descriptor for the child to use as std error

Returns:

The process id of the spawned process
*/
fn spawn_process(prog: str, args: [str], in_fd: int, out_fd: int, err_fd: int)
   -> int unsafe {
    // Note: we have to hold on to these vector references while we hold a
    // pointer to their buffers
    let prog = prog;
    let args = vec::map({|arg| @arg }, args);
    let argv = arg_vec(prog, args);
    let pid =
        rustrt::rust_run_program(vec::unsafe::to_ptr(argv), in_fd, out_fd,
                                 err_fd);
    ret pid;
}

/*
Function: run_program

Spawns a process and waits for it to terminate

Parameters:

prog - The path to an executable
args - Vector of arguments to pass to the child process

Returns:

The process id
*/
fn run_program(prog: str, args: [str]) -> int {
    ret waitpid(spawn_process(prog, args, 0, 0, 0));
}

/*
Function: start_program

Spawns a process and returns a boxed <program_res>

The returned value is a boxed resource containing a <program> object that can
be used for sending and recieving data over the standard file descriptors.
The resource will ensure that file descriptors are closed properly.

Parameters:

prog - The path to an executable
args - Vector of arguments to pass to the child process

Returns:

A boxed resource of <program>
*/
fn start_program(prog: str, args: [str]) -> @program_res {
    let pipe_input = os::pipe();
    let pipe_output = os::pipe();
    let pipe_err = os::pipe();
    let pid =
        spawn_process(prog, args, pipe_input.in, pipe_output.out,
                      pipe_err.out);

    if pid == -1 { fail; }
    os::libc::close(pipe_input.in);
    os::libc::close(pipe_output.out);
    os::libc::close(pipe_err.out);
    obj new_program(pid: int,
                    mutable in_fd: int,
                    out_file: os::libc::FILE,
                    err_file: os::libc::FILE,
                    mutable finished: bool) {
        fn get_id() -> int { ret pid; }
        fn input() -> io::writer {
            ret io::new_writer(io::fd_buf_writer(in_fd, option::none));
        }
        fn output() -> io::reader {
            ret io::new_reader(io::FILE_buf_reader(out_file, option::none));
        }
        fn err() -> io::reader {
            ret io::new_reader(io::FILE_buf_reader(err_file, option::none));
        }
        fn close_input() {
            let invalid_fd = -1;
            if in_fd != invalid_fd {
                os::libc::close(in_fd);
                in_fd = invalid_fd;
            }
        }
        fn finish() -> int {
            if finished { ret 0; }
            finished = true;
            self.close_input();
            ret waitpid(pid);
        }
        fn destroy() {
            self.finish();
            os::libc::fclose(out_file);
            os::libc::fclose(err_file);
        }
    }
    ret @program_res(new_program(pid, pipe_input.out,
                                 os::fd_FILE(pipe_output.in),
                                 os::fd_FILE(pipe_err.in), false));
}

fn read_all(rd: io::reader) -> str {
    let buf = "";
    while !rd.eof() {
        let bytes = rd.read_bytes(4096u);
        buf += str::unsafe_from_bytes(bytes);
    }
    ret buf;
}

/*
Function: program_output

Spawns a process, waits for it to exit, and returns the exit code, and
contents of stdout and stderr.

Parameters:

prog - The path to an executable
args - Vector of arguments to pass to the child process

Returns:

A record, {status: int, out: str, err: str} containing the exit code,
the contents of stdout and the contents of stderr.
*/
fn program_output(prog: str, args: [str]) ->
   {status: int, out: str, err: str} {
    let pr = start_program(prog, args);
    pr.close_input();
    let out = read_all(pr.output());
    let err = read_all(pr.err());
    ret {status: pr.finish(), out: out, err: err};
}

/*
Function: waitpid

Waits for a process to exit and returns the exit code
*/
fn waitpid(pid: int) -> int {
    ret waitpid_os(pid);

    #[cfg(target_os = "win32")]
    fn waitpid_os(pid: int) -> int {
        os::waitpid(pid)
    }

    #[cfg(target_os = "linux")]
    #[cfg(target_os = "macos")]
    fn waitpid_os(pid: int) -> int {
        #[cfg(target_os = "linux")]
        fn WIFEXITED(status: int) -> bool {
            (status & 0xff) == 0
        }

        #[cfg(target_os = "macos")]
        fn WIFEXITED(status: int) -> bool {
            (status & 0x7f) == 0
        }

        #[cfg(target_os = "linux")]
        fn WEXITSTATUS(status: int) -> int {
            (status >> 8) & 0xff
        }

        #[cfg(target_os = "macos")]
        fn WEXITSTATUS(status: int) -> int {
            status >> 8
        }

        let status = os::waitpid(pid);
        ret if WIFEXITED(status) {
            WEXITSTATUS(status)
        } else {
            1
        };
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use rust;
use std::iter::*;
use middle::ast::*;

struct ToTokensVec<'a, T: 'a>
{
  v: &'a Vec<T>
}

impl<'a, T: 'a + rust::ToTokens> rust::ToTokens for ToTokensVec<'a, T>
{
  fn to_tokens(&self, cx: &ExtCtxt) -> Vec<rust::TokenTree> {
    let mut tts = Vec::new();
    for e in self.v.iter() {
      tts.extend(e.to_tokens(cx).into_iter());
    }
    tts
  }
}

pub struct PegCompiler<'cx>
{
  top_level_items: Vec<rust::P<rust::Item>>,
  cx: &'cx ExtCtxt<'cx>,
  unique_id: u32,
  current_rule_name: Ident
}

impl<'cx> PegCompiler<'cx>
{
  pub fn compile(cx: &'cx ExtCtxt, grammar: Grammar) -> Box<rust::MacResult + 'cx>
  {
    let mut compiler = PegCompiler{
      top_level_items: Vec::new(),
      cx: cx,
      unique_id: 0,
      current_rule_name: grammar.rules.keys().next().unwrap().clone()
    };
    compiler.compile_peg(&grammar)
  }

  fn compile_peg(&mut self, grammar: &Grammar) -> Box<rust::MacResult + 'cx>
  {
    let parser =
      if grammar.attributes.code_gen.parser {
        Some(self.compile_parser(grammar))
      } else {
        None
      };

    let grammar_name = grammar.name;
    let code = quote_item!(self.cx,
      pub mod $grammar_name
      {
        #![allow(dead_code)]
        #![allow(unused_parens)]

        $parser
      }
    ).unwrap();

    let peg_crate = quote_item!(self.cx,
      extern crate peg;
    ).unwrap();

    let code = match &code.node {
      &rust::ItemMod(ref module) => {
        let mut items = vec![peg_crate];
        items.push_all(module.items.clone().as_slice());
        rust::P(rust::Item {
          ident: code.ident,
          attrs: code.attrs.clone(),
          id: rust::DUMMY_NODE_ID,
          node: rust::ItemMod(rust::Mod{
            inner: rust::DUMMY_SP,
            items: items
          }),
          vis: rust::Visibility::Public,
          span: rust::DUMMY_SP
        })
      },
      _ => panic!("Bug")
    };

    if grammar.attributes.code_printer.parser {
      self.cx.parse_sess.span_diagnostic.handler.note(
        rust::item_to_string(&*code).as_slice());
    }

    rust::MacItems::new(Some(code).into_iter())
  }

  fn compile_parser(&mut self, grammar: &Grammar) -> Vec<rust::P<rust::Item>>
  {
    for rule in grammar.rules.values() {
      let rule_name = rule.name.node.clone();
      let rule_def = self.compile_expression(&rule.def);
      self.top_level_items.push(quote_item!(self.cx,
        fn $rule_name (input: &str, pos: usize) -> Result<usize, String>
        {
          $rule_def
        }
      ).unwrap());
      self.current_rule_name = rule_name;
    }

    let parser_impl = self.compile_entry_point(grammar);

    let items = ToTokensVec{v: &self.top_level_items};

    let mut parser = vec![];
    parser.push(quote_item!(self.cx, pub struct Parser;).unwrap());
    parser.push(quote_item!(self.cx,
        impl Parser
        {
          pub fn new() -> Parser
          {
            Parser
          }
          $items
        }).unwrap());
    parser.push(parser_impl);
    parser
  }

  fn compile_entry_point(&mut self, grammar: &Grammar) -> rust::P<rust::Item>
  {
    let start_rule_name = grammar.attributes.starting_rule;
    (quote_item!(self.cx,
      impl peg::Parser for Parser
      {
        fn parse<'a>(&self, input: &'a str) -> Result<Option<&'a str>, String>
        {
          peg::runtime::make_result(input,
            &Parser::$start_rule_name(input, 0))
        }
      })).unwrap()
  }

  fn compile_expression(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    match &expr.node {
      &StrLiteral(ref lit_str) => {
        self.compile_str_literal(lit_str)
      },
      &AnySingleChar => {
        self.compile_any_single_char()
      },
      &NonTerminalSymbol(id) => {
        self.compile_non_terminal_symbol(id)
      },
      &Sequence(ref seq) => {
        self.compile_sequence(seq.as_slice())
      },
      &Choice(ref choices) => {
        self.compile_choice(choices.as_slice())
      },
      &ZeroOrMore(ref e) => {
        self.compile_zero_or_more(e)
      },
      &OneOrMore(ref e) => {
        self.compile_one_or_more(e)
      },
      &Optional(ref e) => {
        self.compile_optional(e)
      },
      &NotPredicate(ref e) => {
        self.compile_not_predicate(e)
      },
      &AndPredicate(ref e) => {
        self.compile_and_predicate(e)
      },
      &CharacterClass(ref e) => {
        self.compile_character_class(e)
      },
      &SemanticAction(ref e, _) => {
        self.compile_expression(e)
      }
    }
  }

  fn compile_non_terminal_symbol(&mut self, id: Ident) -> rust::P<rust::Expr>
  {
    quote_expr!(self.cx,
      Parser::$id(input, pos)
    )
  }

  fn compile_any_single_char(&mut self) -> rust::P<rust::Expr>
  {
    quote_expr!(self.cx, peg::runtime::any_single_char(input, pos))
  }

  fn compile_str_literal(&mut self, lit_str: &String) -> rust::P<rust::Expr>
  {
    let lit_str = lit_str.as_slice();
    let lit_len = lit_str.len();
    quote_expr!(self.cx,
      peg::runtime::match_literal(input, pos, $lit_str, $lit_len)
    )
  }

  fn map_foldr_expr<'a, F: FnMut(rust::P<rust::Expr>, rust::P<rust::Expr>) -> rust::P<rust::Expr>>(
    &mut self, seq: &'a [Box<Expression>], f: F) -> rust::P<rust::Expr>
  {
    assert!(seq.len() > 0);
    let mut seq_it = seq
      .iter()
      .map(|e| self.compile_expression(e))
      .rev();

    let head = seq_it.next().unwrap();
    seq_it.fold(head, f)
  }

  fn compile_sequence<'a>(&mut self, seq: &'a [Box<Expression>]) -> rust::P<rust::Expr>
  {
    let cx = self.cx;
    self.map_foldr_expr(seq, |tail, head| {
      quote_expr!(cx,
        match $head {
          Ok(pos) => {
            $tail
          }
          x => x
        }
      )
    })
  }

  fn compile_choice<'a>(&mut self, choices: &'a [Box<Expression>]) -> rust::P<rust::Expr>
  {
    let cx = self.cx;
    self.map_foldr_expr(choices, |tail, head| {
      quote_expr!(cx,
        match $head {
          Err(_) => {
            $tail
          }
          x => x
        }
      )
    })
  }

  fn gen_uid(&mut self) -> u32
  {
    self.unique_id += 1;
    self.unique_id - 1
  }

  fn current_lc_rule_name(&self) -> String
  {
    let rule_name = id_to_string(self.current_rule_name);
    string_to_lowercase(&rule_name)
  }

  fn gensym<'a>(&mut self, prefix: &'a str) -> Ident
  {
    rust::gensym_ident(format!(
      "{}_{}_{}", prefix,
        self.current_lc_rule_name(),
        self.gen_uid()).as_slice())
  }

  fn compile_star(&mut self, expr: &rust::P<rust::Expr>) -> rust::P<rust::Expr>
  {
    let fun_name = self.gensym("star");
    let cx = self.cx;
    self.top_level_items.push(quote_item!(cx,
      fn $fun_name(input: &str, pos: usize) -> Result<usize, String>
      {
        let mut npos = pos;
        while npos < input.len() {
          let pos = npos;
          match $expr {
            Ok(pos) => {
              npos = pos;
            },
            _ => break
          }
        }
        Ok(npos)
      }
    ).unwrap());
    quote_expr!(self.cx, Parser::$fun_name(input, pos))
  }

  fn compile_zero_or_more(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    let expr = self.compile_expression(expr);
    self.compile_star(&expr)
  }

  fn compile_one_or_more(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    let expr = self.compile_expression(expr);
    let star_fn = self.compile_star(&expr);
    let fun_name = self.gensym("plus");
    let cx = self.cx;
    self.top_level_items.push(quote_item!(cx,
      fn $fun_name(input: &str, pos: usize) -> Result<usize, String>
      {
        match $expr {
          Ok(pos) => $star_fn,
          x => x
        }
      }
    ).unwrap());
    quote_expr!(self.cx, Parser::$fun_name(input, pos))
  }

  fn compile_optional(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    let expr = self.compile_expression(expr);
    quote_expr!(self.cx,
      match $expr {
        Ok(pos) => Ok(pos),
        _ => Ok(pos)
      }
    )
  }

  fn compile_not_predicate(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    let expr = self.compile_expression(expr);
    quote_expr!(self.cx,
      match $expr {
        Ok(_) => Err(format!("An `!expr` failed.")),
        _ => Ok(pos)
    })
  }

  fn compile_and_predicate(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    let expr = self.compile_expression(expr);
    quote_expr!(self.cx,
      match $expr {
        Ok(_) => Ok(pos),
        x => x
    })
  }

  fn compile_character_class(&mut self, expr: &CharacterClassExpr) -> rust::P<rust::Expr>
  {
    let fun_name = self.gensym("class_char");
    let cx = self.cx;
    assert!(expr.intervals.len() > 0);

    let mut seq_it = expr.intervals.iter();

    let CharacterInterval{lo, hi} = *seq_it.next().unwrap();
    let cond = seq_it.fold(quote_expr!(cx, (current >= $lo && current <= $hi)),
      |accu, &CharacterInterval{lo, hi}| {
        quote_expr!(cx, $accu || (current >= $lo && current <= $hi))
      }
    );

    self.top_level_items.push(quote_item!(cx,
      fn $fun_name(input: &str, pos: usize) -> Result<usize, String>
      {
        let current = input.char_range_at(pos).ch;
        if $cond {
          Ok(input.char_range_at(pos).next)
        } else {
          Err(format!("It doesn't match the character class."))
        }
      }
    ).unwrap());
    quote_expr!(self.cx, Parser::$fun_name(input, pos))
  }
}
<commit_msg>Add feature to avoid warnings due to the runtime code.<commit_after>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use rust;
use std::iter::*;
use middle::ast::*;

struct ToTokensVec<'a, T: 'a>
{
  v: &'a Vec<T>
}

impl<'a, T: 'a + rust::ToTokens> rust::ToTokens for ToTokensVec<'a, T>
{
  fn to_tokens(&self, cx: &ExtCtxt) -> Vec<rust::TokenTree> {
    let mut tts = Vec::new();
    for e in self.v.iter() {
      tts.extend(e.to_tokens(cx).into_iter());
    }
    tts
  }
}

pub struct PegCompiler<'cx>
{
  top_level_items: Vec<rust::P<rust::Item>>,
  cx: &'cx ExtCtxt<'cx>,
  unique_id: u32,
  current_rule_name: Ident
}

impl<'cx> PegCompiler<'cx>
{
  pub fn compile(cx: &'cx ExtCtxt, grammar: Grammar) -> Box<rust::MacResult + 'cx>
  {
    let mut compiler = PegCompiler{
      top_level_items: Vec::new(),
      cx: cx,
      unique_id: 0,
      current_rule_name: grammar.rules.keys().next().unwrap().clone()
    };
    compiler.compile_peg(&grammar)
  }

  fn compile_peg(&mut self, grammar: &Grammar) -> Box<rust::MacResult + 'cx>
  {
    let parser =
      if grammar.attributes.code_gen.parser {
        Some(self.compile_parser(grammar))
      } else {
        None
      };

    let grammar_name = grammar.name;
    let code = quote_item!(self.cx,
      pub mod $grammar_name
      {
        #![allow(dead_code)]
        #![allow(unused_parens)]
        #![allow(plugin_as_library)] // for the runtime.

        $parser
      }
    ).unwrap();

    let peg_crate = quote_item!(self.cx,
      extern crate peg;
    ).unwrap();

    let code = match &code.node {
      &rust::ItemMod(ref module) => {
        let mut items = vec![peg_crate];
        items.push_all(module.items.clone().as_slice());
        rust::P(rust::Item {
          ident: code.ident,
          attrs: code.attrs.clone(),
          id: rust::DUMMY_NODE_ID,
          node: rust::ItemMod(rust::Mod{
            inner: rust::DUMMY_SP,
            items: items
          }),
          vis: rust::Visibility::Public,
          span: rust::DUMMY_SP
        })
      },
      _ => panic!("Bug")
    };

    if grammar.attributes.code_printer.parser {
      self.cx.parse_sess.span_diagnostic.handler.note(
        rust::item_to_string(&*code).as_slice());
    }

    rust::MacItems::new(Some(code).into_iter())
  }

  fn compile_parser(&mut self, grammar: &Grammar) -> Vec<rust::P<rust::Item>>
  {
    for rule in grammar.rules.values() {
      let rule_name = rule.name.node.clone();
      let rule_def = self.compile_expression(&rule.def);
      self.top_level_items.push(quote_item!(self.cx,
        fn $rule_name (input: &str, pos: usize) -> Result<usize, String>
        {
          $rule_def
        }
      ).unwrap());
      self.current_rule_name = rule_name;
    }

    let parser_impl = self.compile_entry_point(grammar);

    let items = ToTokensVec{v: &self.top_level_items};

    let mut parser = vec![];
    parser.push(quote_item!(self.cx, pub struct Parser;).unwrap());
    parser.push(quote_item!(self.cx,
        impl Parser
        {
          pub fn new() -> Parser
          {
            Parser
          }
          $items
        }).unwrap());
    parser.push(parser_impl);
    parser
  }

  fn compile_entry_point(&mut self, grammar: &Grammar) -> rust::P<rust::Item>
  {
    let start_rule_name = grammar.attributes.starting_rule;
    (quote_item!(self.cx,
      impl peg::Parser for Parser
      {
        fn parse<'a>(&self, input: &'a str) -> Result<Option<&'a str>, String>
        {
          peg::runtime::make_result(input,
            &Parser::$start_rule_name(input, 0))
        }
      })).unwrap()
  }

  fn compile_expression(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    match &expr.node {
      &StrLiteral(ref lit_str) => {
        self.compile_str_literal(lit_str)
      },
      &AnySingleChar => {
        self.compile_any_single_char()
      },
      &NonTerminalSymbol(id) => {
        self.compile_non_terminal_symbol(id)
      },
      &Sequence(ref seq) => {
        self.compile_sequence(seq.as_slice())
      },
      &Choice(ref choices) => {
        self.compile_choice(choices.as_slice())
      },
      &ZeroOrMore(ref e) => {
        self.compile_zero_or_more(e)
      },
      &OneOrMore(ref e) => {
        self.compile_one_or_more(e)
      },
      &Optional(ref e) => {
        self.compile_optional(e)
      },
      &NotPredicate(ref e) => {
        self.compile_not_predicate(e)
      },
      &AndPredicate(ref e) => {
        self.compile_and_predicate(e)
      },
      &CharacterClass(ref e) => {
        self.compile_character_class(e)
      },
      &SemanticAction(ref e, _) => {
        self.compile_expression(e)
      }
    }
  }

  fn compile_non_terminal_symbol(&mut self, id: Ident) -> rust::P<rust::Expr>
  {
    quote_expr!(self.cx,
      Parser::$id(input, pos)
    )
  }

  fn compile_any_single_char(&mut self) -> rust::P<rust::Expr>
  {
    quote_expr!(self.cx, peg::runtime::any_single_char(input, pos))
  }

  fn compile_str_literal(&mut self, lit_str: &String) -> rust::P<rust::Expr>
  {
    let lit_str = lit_str.as_slice();
    let lit_len = lit_str.len();
    quote_expr!(self.cx,
      peg::runtime::match_literal(input, pos, $lit_str, $lit_len)
    )
  }

  fn map_foldr_expr<'a, F: FnMut(rust::P<rust::Expr>, rust::P<rust::Expr>) -> rust::P<rust::Expr>>(
    &mut self, seq: &'a [Box<Expression>], f: F) -> rust::P<rust::Expr>
  {
    assert!(seq.len() > 0);
    let mut seq_it = seq
      .iter()
      .map(|e| self.compile_expression(e))
      .rev();

    let head = seq_it.next().unwrap();
    seq_it.fold(head, f)
  }

  fn compile_sequence<'a>(&mut self, seq: &'a [Box<Expression>]) -> rust::P<rust::Expr>
  {
    let cx = self.cx;
    self.map_foldr_expr(seq, |tail, head| {
      quote_expr!(cx,
        match $head {
          Ok(pos) => {
            $tail
          }
          x => x
        }
      )
    })
  }

  fn compile_choice<'a>(&mut self, choices: &'a [Box<Expression>]) -> rust::P<rust::Expr>
  {
    let cx = self.cx;
    self.map_foldr_expr(choices, |tail, head| {
      quote_expr!(cx,
        match $head {
          Err(_) => {
            $tail
          }
          x => x
        }
      )
    })
  }

  fn gen_uid(&mut self) -> u32
  {
    self.unique_id += 1;
    self.unique_id - 1
  }

  fn current_lc_rule_name(&self) -> String
  {
    let rule_name = id_to_string(self.current_rule_name);
    string_to_lowercase(&rule_name)
  }

  fn gensym<'a>(&mut self, prefix: &'a str) -> Ident
  {
    rust::gensym_ident(format!(
      "{}_{}_{}", prefix,
        self.current_lc_rule_name(),
        self.gen_uid()).as_slice())
  }

  fn compile_star(&mut self, expr: &rust::P<rust::Expr>) -> rust::P<rust::Expr>
  {
    let fun_name = self.gensym("star");
    let cx = self.cx;
    self.top_level_items.push(quote_item!(cx,
      fn $fun_name(input: &str, pos: usize) -> Result<usize, String>
      {
        let mut npos = pos;
        while npos < input.len() {
          let pos = npos;
          match $expr {
            Ok(pos) => {
              npos = pos;
            },
            _ => break
          }
        }
        Ok(npos)
      }
    ).unwrap());
    quote_expr!(self.cx, Parser::$fun_name(input, pos))
  }

  fn compile_zero_or_more(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    let expr = self.compile_expression(expr);
    self.compile_star(&expr)
  }

  fn compile_one_or_more(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    let expr = self.compile_expression(expr);
    let star_fn = self.compile_star(&expr);
    let fun_name = self.gensym("plus");
    let cx = self.cx;
    self.top_level_items.push(quote_item!(cx,
      fn $fun_name(input: &str, pos: usize) -> Result<usize, String>
      {
        match $expr {
          Ok(pos) => $star_fn,
          x => x
        }
      }
    ).unwrap());
    quote_expr!(self.cx, Parser::$fun_name(input, pos))
  }

  fn compile_optional(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    let expr = self.compile_expression(expr);
    quote_expr!(self.cx,
      match $expr {
        Ok(pos) => Ok(pos),
        _ => Ok(pos)
      }
    )
  }

  fn compile_not_predicate(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    let expr = self.compile_expression(expr);
    quote_expr!(self.cx,
      match $expr {
        Ok(_) => Err(format!("An `!expr` failed.")),
        _ => Ok(pos)
    })
  }

  fn compile_and_predicate(&mut self, expr: &Box<Expression>) -> rust::P<rust::Expr>
  {
    let expr = self.compile_expression(expr);
    quote_expr!(self.cx,
      match $expr {
        Ok(_) => Ok(pos),
        x => x
    })
  }

  fn compile_character_class(&mut self, expr: &CharacterClassExpr) -> rust::P<rust::Expr>
  {
    let fun_name = self.gensym("class_char");
    let cx = self.cx;
    assert!(expr.intervals.len() > 0);

    let mut seq_it = expr.intervals.iter();

    let CharacterInterval{lo, hi} = *seq_it.next().unwrap();
    let cond = seq_it.fold(quote_expr!(cx, (current >= $lo && current <= $hi)),
      |accu, &CharacterInterval{lo, hi}| {
        quote_expr!(cx, $accu || (current >= $lo && current <= $hi))
      }
    );

    self.top_level_items.push(quote_item!(cx,
      fn $fun_name(input: &str, pos: usize) -> Result<usize, String>
      {
        let current = input.char_range_at(pos).ch;
        if $cond {
          Ok(input.char_range_at(pos).next)
        } else {
          Err(format!("It doesn't match the character class."))
        }
      }
    ).unwrap());
    quote_expr!(self.cx, Parser::$fun_name(input, pos))
  }
}
<|endoftext|>


<commit_before>#![cfg(feature = "resource-groups")]

extern crate rusoto_core;
extern crate rusoto_resource_groups;

use rusoto_core::Region;
use rusoto_resource_groups::{ListGroupsInput, ResourceGroups, ResourceGroupsClient};

#[test]
fn should_list_groups() {
    let client = ResourceGroupsClient::new(Region::UsEast1);
    let request = ListGroupsInput::default();

    let result = client.list_groups(request).sync().unwrap();
    println!("{:#?}", result);
    assert!(result.groups.is_some());
}
<commit_msg>fix breaking change that affected resourcegroups integration test<commit_after>#![cfg(feature = "resource-groups")]

extern crate rusoto_core;
extern crate rusoto_resource_groups;

use rusoto_core::Region;
use rusoto_resource_groups::{ListGroupsInput, ResourceGroups, ResourceGroupsClient};

#[test]
fn should_list_groups() {
    let client = ResourceGroupsClient::new(Region::UsEast1);
    let request = ListGroupsInput::default();

    let result = client.list_groups(request).sync().unwrap();
    println!("{:#?}", result);
    assert!(result.group_identifiers.is_some());
}
<|endoftext|>


<commit_before>extern crate argparse;
extern crate ansi_term;
extern crate rand;
extern crate random_things;

use rand::{Rng};
use argparse::{ArgumentParser, Store};
use ansi_term::Colour;
use random_things::random_string;

fn main() {
    let mut length:u32 = rand::thread_rng().gen_range(10, 21);
    let minimum_length = 10;
    let warning_message = Colour::Red.paint("WARNING: Password length should be at least: ");

    {  // this block limits scope of borrows by ap.refer() method
        let mut ap = ArgumentParser::new();
        ap.set_description("This tool generates a random password");
        ap.refer(&mut length)
        .add_option(&["-l", "--length"], Store,
        "Length of password, defaults to a random length between 10 and 20");
        ap.parse_args_or_exit();
    }

    if length < minimum_length {
        println!("{}{}", warning_message, Colour::Red.paint(length.to_string()));
    }

    println!("Generated password of length: {}", Colour::Green.paint(length.to_string()));
    println!("Password: {}", Colour::Green.paint(random_string(length)));
}
<commit_msg>fixed warning message error<commit_after>extern crate argparse;
extern crate ansi_term;
extern crate rand;
extern crate random_things;

use rand::{Rng};
use argparse::{ArgumentParser, Store};
use ansi_term::Colour;
use random_things::random_string;

fn main() {
    let mut length:u32 = rand::thread_rng().gen_range(10, 21);
    let minimum_length = 10;
    let warning_message = Colour::Red.paint("WARNING: Password length should be at least: ");

    {  // this block limits scope of borrows by ap.refer() method
        let mut ap = ArgumentParser::new();
        ap.set_description("This tool generates a random password");
        ap.refer(&mut length)
        .add_option(&["-l", "--length"], Store,
        "Length of password, defaults to a random length between 10 and 20");
        ap.parse_args_or_exit();
    }

    if length < minimum_length {
        println!("{}{}", warning_message, Colour::Red.paint(minimum_length.to_string()));
    }

    println!("Generated password of length: {}", Colour::Green.paint(length.to_string()));
    println!("Password: {}", Colour::Green.paint(random_string(length)));
}
<|endoftext|>


<commit_before>use cocoa::base::id;

pub struct BlitCommandEncoder(id);

impl_from_into_raw!(BlitCommandEncoder, of protocol "MTLBlitCommandEncoder");

<commit_msg>formatting<commit_after>use cocoa::base::id;

pub struct BlitCommandEncoder(id);

impl_from_into_raw!(BlitCommandEncoder, of protocol "MTLBlitCommandEncoder");
<|endoftext|>


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

use quire::validate as V;
use super::super::context::{Context};
use super::super::packages;
use super::generic::{run_command_at_env, capture_command};
use builder::distrib::Distribution;
use file_util::Dir;
use build_step::{BuildStep, VersionError, StepError, Digest, Config, Guard};

#[derive(RustcDecodable, Debug, Clone)]
pub struct PipConfig {
    pub find_links: Vec<String>,
    pub index_urls: Vec<String>,
    pub trusted_hosts: Vec<String>,
    pub dependencies: bool,
    pub cache_wheels: bool,
    pub install_python: bool,
    pub python_exe: Option<String>,
    pub allow_pre_releases: bool,
}

impl PipConfig {
    pub fn config() -> V::Structure<'static> {
        V::Structure::new()
        .member("dependencies", V::Scalar::new().default(false).optional())
        .member("cache_wheels", V::Scalar::new().default(true))
        .member("find_links", V::Sequence::new(V::Scalar::new()))
        .member("index_urls", V::Sequence::new(V::Scalar::new()))
        .member("trusted_hosts", V::Sequence::new(V::Scalar::new()))
        .member("python_exe", V::Scalar::new().optional())
        .member("install_python", V::Scalar::new().default(true))
        .member("allow_pre_releases", V::Scalar::new().default(false))
    }
}

#[derive(Debug)]
pub struct Py2Install(Vec<String>);
tuple_struct_decode!(Py2Install);

impl Py2Install {
    pub fn config() -> V::Sequence<'static> {
        V::Sequence::new(V::Scalar::new())
    }
}

#[derive(Debug)]
pub struct Py2Requirements(PathBuf);
tuple_struct_decode!(Py2Requirements);

impl Py2Requirements {
    pub fn config() -> V::Scalar {
        V::Scalar::new().default("requirements.txt")
    }
}

#[derive(Debug)]
pub struct Py3Install(Vec<String>);
tuple_struct_decode!(Py3Install);

impl Py3Install {
    pub fn config() -> V::Sequence<'static> {
        V::Sequence::new(V::Scalar::new())
    }
}

#[derive(Debug)]
pub struct Py3Requirements(PathBuf);
tuple_struct_decode!(Py3Requirements);

impl Py3Requirements {
    pub fn config() -> V::Scalar {
        V::Scalar::new().default("requirements.txt")
    }
}

impl Default for PipConfig {
    fn default() -> PipConfig {
        PipConfig {
            find_links: Vec::new(),
            index_urls: Vec::new(),
            trusted_hosts: Vec::new(),
            dependencies: false,
            cache_wheels: true,
            install_python: true,
            python_exe: None,
            allow_pre_releases: false,
        }
    }
}

pub fn scan_features(settings: &PipConfig, ver: u8, pkgs: &Vec<String>)
    -> Vec<packages::Package>
{
    let mut res = vec!();
    res.push(packages::BuildEssential);
    if ver == 2 {
        if settings.install_python {
            res.push(packages::Python2);
            res.push(packages::Python2Dev);
        }
        res.push(packages::PipPy2);
    } else {
        if settings.install_python {
            res.push(packages::Python3);
            res.push(packages::Python3Dev);
        }
        res.push(packages::PipPy3);
    }
    for name in pkgs.iter() {
        if name[..].starts_with("git+https") {
            res.push(packages::Git);
            res.push(packages::Https);
        } else if name[..].starts_with("git+") {
            res.push(packages::Git);
        } else if name[..].starts_with("hg+https") {
            res.push(packages::Mercurial);
            res.push(packages::Https);
        } else if name[..].starts_with("hg+") {
            res.push(packages::Mercurial);
        }
    }
    return res;
}

fn pip_args(ctx: &mut Context, ver: u8) -> Vec<String> {
    let mut args = vec!(
        ctx.pip_settings.python_exe.clone()
        .unwrap_or((if ver == 2 { "python2" } else { "python3" }).to_string()),
        "-m".to_string(), "pip".to_string(),
        "install".to_string(),
        "--ignore-installed".to_string(),
        );
    if ctx.pip_settings.index_urls.len() > 0 {
        let mut indexes = ctx.pip_settings.index_urls.iter();
        if let Some(ref lnk) = indexes.next() {
            args.push(format!("--index-url={}", lnk));
            for lnk in indexes {
                args.push(format!("--extra-index-url={}", lnk));
            }
        }
    }
    ctx.pip_settings.trusted_hosts.iter().map(|h| {
        args.push("--trusted-host".to_string());
        args.push(h.to_string());
    }).last();
    if !ctx.pip_settings.dependencies {
        args.push("--no-deps".to_string());
    }
    for lnk in ctx.pip_settings.find_links.iter() {
        args.push(format!("--find-links={}", lnk));
    }
    if ctx.pip_settings.allow_pre_releases {
        args.push("--pre".to_string());
    }
    return args;
}

pub fn pip_install(distro: &mut Box<Distribution>, ctx: &mut Context,
    ver: u8, pkgs: &Vec<String>)
    -> Result<(), String>
{
    let features = scan_features(&ctx.pip_settings, ver, pkgs);
    packages::ensure_packages(distro, ctx, &features)?;
    let mut pip_cli = pip_args(ctx, ver);
    pip_cli.extend(pkgs.clone().into_iter());
    run_command_at_env(ctx, &pip_cli, &Path::new("/work"), &[
        ("PYTHONPATH", "/tmp/non-existent:/tmp/pip-install")])
}

pub fn pip_requirements(distro: &mut Box<Distribution>, ctx: &mut Context,
    ver: u8, reqtxt: &Path)
    -> Result<(), String>
{
    let f = File::open(&Path::new("/work").join(reqtxt))
        .map_err(|e| format!("Can't open requirements file: {}", e))?;
    let f = BufReader::new(f);
    let mut names = vec!();
    for line in f.lines() {
        let line = line
                .map_err(|e| format!("Error reading requirements: {}", e))?;
        let chunk = line[..].trim();
        // Ignore empty lines and comments
        if chunk.len() == 0 || chunk.starts_with("#") {
            continue;
        }
        names.push(chunk.to_string());
    }

    let features = scan_features(&ctx.pip_settings, ver, &names);
    packages::ensure_packages(distro, ctx, &features)?;
    let mut pip_cli = pip_args(ctx, ver);
    pip_cli.push("--requirement".to_string());
    pip_cli.push(reqtxt.to_str()
        .ok_or("Incorrect path for requirements file")?.to_string());
    run_command_at_env(ctx, &pip_cli, &Path::new("/work"), &[
        ("PYTHONPATH", "/tmp/non-existent:/tmp/pip-install")])
}

pub fn configure(ctx: &mut Context) -> Result<(), String> {
    let cache_root = Path::new("/vagga/root/tmp/pip-cache");
    try_msg!(Dir::new(&cache_root).recursive(true).create(),
         "Error creating cache dir {d:?}: {err}", d=cache_root);

    ctx.add_cache_dir(Path::new("/tmp/pip-cache/http"),
                           "pip-cache-http".to_string())?;

    if ctx.pip_settings.cache_wheels {
        let cache_dir = format!("pip-cache-wheels-{}", ctx.binary_ident);
        ctx.add_cache_dir(Path::new("/tmp/pip-cache/wheels"), cache_dir)?;
    } // else just write files in tmp

    ctx.environ.insert("PIP_CACHE_DIR".to_string(),
                       "/tmp/pip-cache".to_string());
    Ok(())
}

pub fn freeze(ctx: &mut Context) -> Result<(), String> {
    use std::fs::File;  // TODO(tailhook) migrate whole module
    use std::io::Write;  // TODO(tailhook) migrate whole module
    if ctx.featured_packages.contains(&packages::PipPy2) {
        let python_exe = ctx.pip_settings.python_exe.clone()
                         .unwrap_or("python2".to_string());
        capture_command(ctx, &[python_exe,
                "-m".to_string(),
                "pip".to_string(),
                "freeze".to_string(),
            ], &[("PYTHONPATH", "/tmp/non-existent:/tmp/pip-install")])
            .and_then(|out| {
                File::create("/vagga/container/pip2-freeze.txt")
                .and_then(|mut f| f.write_all(&out))
                .map_err(|e| format!("Error dumping package list: {}", e))
            })?;
    }
    if ctx.featured_packages.contains(&packages::PipPy3) {
        let python_exe = ctx.pip_settings.python_exe.clone()
                         .unwrap_or("python3".to_string());
        capture_command(ctx, &[python_exe,
                "-m".to_string(),
                "pip".to_string(),
                "freeze".to_string(),
            ], &[("PYTHONPATH", "/tmp/non-existent:/tmp/pip-install")])
            .and_then(|out| {
                File::create("/vagga/container/pip3-freeze.txt")
                .and_then(|mut f| f.write_all(&out))
                .map_err(|e| format!("Error dumping package list: {}", e))
            })?;
    }
    Ok(())
}

impl BuildStep for PipConfig {
    fn name(&self) -> &'static str { "PipConfig" }
    fn hash(&self, _cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        hash.field("find_links", &self.find_links);
        hash.field("index_urls", &self.index_urls);
        hash.field("trusted_hosts", &self.trusted_hosts);
        hash.field("dependencies", self.dependencies);
        hash.field("cache_wheels", self.cache_wheels);
        hash.field("install_python", self.install_python);
        hash.field("allow_pre_releases", self.allow_pre_releases);
        hash.opt_field("python_exe", &self.python_exe);
        Ok(())
    }
    fn build(&self, guard: &mut Guard, _build: bool)
        -> Result<(), StepError>
    {
        guard.ctx.pip_settings = self.clone();
        Ok(())
    }
    fn is_dependent_on(&self) -> Option<&str> {
        None
    }
}

impl BuildStep for Py2Install {
    fn name(&self) -> &'static str { "Py2Install" }
    fn hash(&self, _cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        hash.field("packages", &self.0);
        Ok(())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        configure(&mut guard.ctx)?;
        if build {
            pip_install(&mut guard.distro, &mut guard.ctx, 2, &self.0)?;
        }
        Ok(())
    }
    fn is_dependent_on(&self) -> Option<&str> {
        None
    }
}

impl BuildStep for Py3Install {
    fn name(&self) -> &'static str { "Py3Install" }
    fn hash(&self, _cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        hash.field("packages", &self.0);
        Ok(())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        configure(&mut guard.ctx)?;
        if build {
            pip_install(&mut guard.distro, &mut guard.ctx, 3, &self.0)?;
        }
        Ok(())
    }
    fn is_dependent_on(&self) -> Option<&str> {
        None
    }
}

fn parse_req_filename(line: &str) -> Option<&str> {
    let res = vec!["-r", "--requirement ", "--requirement=",
                   "-c", "--constraint ", "--constraint="];
    for prefix in res.iter() {
        if line.starts_with(prefix) {
            return Some(line[prefix.len()..].trim());
        }
    }
    return None;
}

fn version_req(hash: &mut Digest, fname: &Path, used: &mut HashSet<String>) ->
               Result<(), VersionError> {

    let path = Path::new("/work").join(fname).canonicalize()
                   .map_err(|e| VersionError::Io(e, fname.to_path_buf()))?;

    let name = format!("{:?}", path);
    if used.contains(&name[..]) {
        return Err(VersionError::String(
            format!("Cyclic requirement: {}", name)))
    }

    used.insert(name);

    let f = File::open(&path).map_err(|e| VersionError::Io(e, path.clone()))?;

    let f = BufReader::new(f);
    for line in f.lines() {
        let line = line.map_err(|e| VersionError::Io(e, path.clone()))?;
        let chunk = line[..].trim();
        // Ignore empty lines and comments
        if chunk.len() == 0 || chunk.starts_with("#") {
            continue;
        }
        if let Some(req) = parse_req_filename(chunk) {
            version_req(hash, &fname.parent().unwrap().join(req), used)?;
            continue;
        }
        // Should we also ignore the order?
        hash.field("line", chunk);
    }
    Ok(())
}

impl BuildStep for Py2Requirements {
    fn name(&self) -> &'static str { "Py2Requirements" }
    fn hash(&self, _cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        version_req(hash, &self.0, &mut HashSet::new())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        configure(&mut guard.ctx)?;
        if build {
            pip_requirements(&mut guard.distro, &mut guard.ctx, 2, &self.0)?;
        }
        Ok(())
    }
    fn is_dependent_on(&self) -> Option<&str> {
        None
    }
}

impl BuildStep for Py3Requirements {
    fn name(&self) -> &'static str { "Py3Requirements" }
    fn hash(&self, _cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        version_req(hash, &self.0, &mut HashSet::new())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        configure(&mut guard.ctx)?;
        if build {
            pip_requirements(&mut guard.distro, &mut guard.ctx, 3, &self.0)?;
        }
        Ok(())
    }
    fn is_dependent_on(&self) -> Option<&str> {
        None
    }
}
<commit_msg>Fixes hashes for pip commands (broken by #414)<commit_after>use std::fs::File;
use std::collections::HashSet;
use std::io::{BufReader, BufRead};
use std::path::{Path, PathBuf};

use quire::validate as V;
use super::super::context::{Context};
use super::super::packages;
use super::generic::{run_command_at_env, capture_command};
use builder::distrib::Distribution;
use file_util::Dir;
use build_step::{BuildStep, VersionError, StepError, Digest, Config, Guard};

#[derive(RustcDecodable, Debug, Clone)]
pub struct PipConfig {
    pub find_links: Vec<String>,
    pub index_urls: Vec<String>,
    pub trusted_hosts: Vec<String>,
    pub dependencies: bool,
    pub cache_wheels: bool,
    pub install_python: bool,
    pub python_exe: Option<String>,
    pub allow_pre_releases: bool,
}

impl PipConfig {
    pub fn config() -> V::Structure<'static> {
        V::Structure::new()
        .member("dependencies", V::Scalar::new().default(false).optional())
        .member("cache_wheels", V::Scalar::new().default(true))
        .member("find_links", V::Sequence::new(V::Scalar::new()))
        .member("index_urls", V::Sequence::new(V::Scalar::new()))
        .member("trusted_hosts", V::Sequence::new(V::Scalar::new()))
        .member("python_exe", V::Scalar::new().optional())
        .member("install_python", V::Scalar::new().default(true))
        .member("allow_pre_releases", V::Scalar::new().default(false))
    }
}

#[derive(Debug)]
pub struct Py2Install(Vec<String>);
tuple_struct_decode!(Py2Install);

impl Py2Install {
    pub fn config() -> V::Sequence<'static> {
        V::Sequence::new(V::Scalar::new())
    }
}

#[derive(Debug)]
pub struct Py2Requirements(PathBuf);
tuple_struct_decode!(Py2Requirements);

impl Py2Requirements {
    pub fn config() -> V::Scalar {
        V::Scalar::new().default("requirements.txt")
    }
}

#[derive(Debug)]
pub struct Py3Install(Vec<String>);
tuple_struct_decode!(Py3Install);

impl Py3Install {
    pub fn config() -> V::Sequence<'static> {
        V::Sequence::new(V::Scalar::new())
    }
}

#[derive(Debug)]
pub struct Py3Requirements(PathBuf);
tuple_struct_decode!(Py3Requirements);

impl Py3Requirements {
    pub fn config() -> V::Scalar {
        V::Scalar::new().default("requirements.txt")
    }
}

impl Default for PipConfig {
    fn default() -> PipConfig {
        PipConfig {
            find_links: Vec::new(),
            index_urls: Vec::new(),
            trusted_hosts: Vec::new(),
            dependencies: false,
            cache_wheels: true,
            install_python: true,
            python_exe: None,
            allow_pre_releases: false,
        }
    }
}

pub fn scan_features(settings: &PipConfig, ver: u8, pkgs: &Vec<String>)
    -> Vec<packages::Package>
{
    let mut res = vec!();
    res.push(packages::BuildEssential);
    if ver == 2 {
        if settings.install_python {
            res.push(packages::Python2);
            res.push(packages::Python2Dev);
        }
        res.push(packages::PipPy2);
    } else {
        if settings.install_python {
            res.push(packages::Python3);
            res.push(packages::Python3Dev);
        }
        res.push(packages::PipPy3);
    }
    for name in pkgs.iter() {
        if name[..].starts_with("git+https") {
            res.push(packages::Git);
            res.push(packages::Https);
        } else if name[..].starts_with("git+") {
            res.push(packages::Git);
        } else if name[..].starts_with("hg+https") {
            res.push(packages::Mercurial);
            res.push(packages::Https);
        } else if name[..].starts_with("hg+") {
            res.push(packages::Mercurial);
        }
    }
    return res;
}

fn pip_args(ctx: &mut Context, ver: u8) -> Vec<String> {
    let mut args = vec!(
        ctx.pip_settings.python_exe.clone()
        .unwrap_or((if ver == 2 { "python2" } else { "python3" }).to_string()),
        "-m".to_string(), "pip".to_string(),
        "install".to_string(),
        "--ignore-installed".to_string(),
        );
    if ctx.pip_settings.index_urls.len() > 0 {
        let mut indexes = ctx.pip_settings.index_urls.iter();
        if let Some(ref lnk) = indexes.next() {
            args.push(format!("--index-url={}", lnk));
            for lnk in indexes {
                args.push(format!("--extra-index-url={}", lnk));
            }
        }
    }
    ctx.pip_settings.trusted_hosts.iter().map(|h| {
        args.push("--trusted-host".to_string());
        args.push(h.to_string());
    }).last();
    if !ctx.pip_settings.dependencies {
        args.push("--no-deps".to_string());
    }
    for lnk in ctx.pip_settings.find_links.iter() {
        args.push(format!("--find-links={}", lnk));
    }
    if ctx.pip_settings.allow_pre_releases {
        args.push("--pre".to_string());
    }
    return args;
}

pub fn pip_install(distro: &mut Box<Distribution>, ctx: &mut Context,
    ver: u8, pkgs: &Vec<String>)
    -> Result<(), String>
{
    let features = scan_features(&ctx.pip_settings, ver, pkgs);
    packages::ensure_packages(distro, ctx, &features)?;
    let mut pip_cli = pip_args(ctx, ver);
    pip_cli.extend(pkgs.clone().into_iter());
    run_command_at_env(ctx, &pip_cli, &Path::new("/work"), &[
        ("PYTHONPATH", "/tmp/non-existent:/tmp/pip-install")])
}

pub fn pip_requirements(distro: &mut Box<Distribution>, ctx: &mut Context,
    ver: u8, reqtxt: &Path)
    -> Result<(), String>
{
    let f = File::open(&Path::new("/work").join(reqtxt))
        .map_err(|e| format!("Can't open requirements file: {}", e))?;
    let f = BufReader::new(f);
    let mut names = vec!();
    for line in f.lines() {
        let line = line
                .map_err(|e| format!("Error reading requirements: {}", e))?;
        let chunk = line[..].trim();
        // Ignore empty lines and comments
        if chunk.len() == 0 || chunk.starts_with("#") {
            continue;
        }
        names.push(chunk.to_string());
    }

    let features = scan_features(&ctx.pip_settings, ver, &names);
    packages::ensure_packages(distro, ctx, &features)?;
    let mut pip_cli = pip_args(ctx, ver);
    pip_cli.push("--requirement".to_string());
    pip_cli.push(reqtxt.to_str()
        .ok_or("Incorrect path for requirements file")?.to_string());
    run_command_at_env(ctx, &pip_cli, &Path::new("/work"), &[
        ("PYTHONPATH", "/tmp/non-existent:/tmp/pip-install")])
}

pub fn configure(ctx: &mut Context) -> Result<(), String> {
    let cache_root = Path::new("/vagga/root/tmp/pip-cache");
    try_msg!(Dir::new(&cache_root).recursive(true).create(),
         "Error creating cache dir {d:?}: {err}", d=cache_root);

    ctx.add_cache_dir(Path::new("/tmp/pip-cache/http"),
                           "pip-cache-http".to_string())?;

    if ctx.pip_settings.cache_wheels {
        let cache_dir = format!("pip-cache-wheels-{}", ctx.binary_ident);
        ctx.add_cache_dir(Path::new("/tmp/pip-cache/wheels"), cache_dir)?;
    } // else just write files in tmp

    ctx.environ.insert("PIP_CACHE_DIR".to_string(),
                       "/tmp/pip-cache".to_string());
    Ok(())
}

pub fn freeze(ctx: &mut Context) -> Result<(), String> {
    use std::fs::File;  // TODO(tailhook) migrate whole module
    use std::io::Write;  // TODO(tailhook) migrate whole module
    if ctx.featured_packages.contains(&packages::PipPy2) {
        let python_exe = ctx.pip_settings.python_exe.clone()
                         .unwrap_or("python2".to_string());
        capture_command(ctx, &[python_exe,
                "-m".to_string(),
                "pip".to_string(),
                "freeze".to_string(),
            ], &[("PYTHONPATH", "/tmp/non-existent:/tmp/pip-install")])
            .and_then(|out| {
                File::create("/vagga/container/pip2-freeze.txt")
                .and_then(|mut f| f.write_all(&out))
                .map_err(|e| format!("Error dumping package list: {}", e))
            })?;
    }
    if ctx.featured_packages.contains(&packages::PipPy3) {
        let python_exe = ctx.pip_settings.python_exe.clone()
                         .unwrap_or("python3".to_string());
        capture_command(ctx, &[python_exe,
                "-m".to_string(),
                "pip".to_string(),
                "freeze".to_string(),
            ], &[("PYTHONPATH", "/tmp/non-existent:/tmp/pip-install")])
            .and_then(|out| {
                File::create("/vagga/container/pip3-freeze.txt")
                .and_then(|mut f| f.write_all(&out))
                .map_err(|e| format!("Error dumping package list: {}", e))
            })?;
    }
    Ok(())
}

impl BuildStep for PipConfig {
    fn name(&self) -> &'static str { "PipConfig" }
    fn hash(&self, _cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        hash.field("find_links", &self.find_links);
        hash.field("index_urls", &self.index_urls);
        hash.field("trusted_hosts", &self.trusted_hosts);
        hash.field("dependencies", self.dependencies);
        hash.field("cache_wheels", self.cache_wheels);
        hash.field("install_python", self.install_python);
        if self.allow_pre_releases {
            hash.field("allow_pre_releases", self.allow_pre_releases);
        }
        hash.opt_field("python_exe", &self.python_exe);
        Ok(())
    }
    fn build(&self, guard: &mut Guard, _build: bool)
        -> Result<(), StepError>
    {
        guard.ctx.pip_settings = self.clone();
        Ok(())
    }
    fn is_dependent_on(&self) -> Option<&str> {
        None
    }
}

impl BuildStep for Py2Install {
    fn name(&self) -> &'static str { "Py2Install" }
    fn hash(&self, _cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        hash.field("packages", &self.0);
        Ok(())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        configure(&mut guard.ctx)?;
        if build {
            pip_install(&mut guard.distro, &mut guard.ctx, 2, &self.0)?;
        }
        Ok(())
    }
    fn is_dependent_on(&self) -> Option<&str> {
        None
    }
}

impl BuildStep for Py3Install {
    fn name(&self) -> &'static str { "Py3Install" }
    fn hash(&self, _cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        hash.field("packages", &self.0);
        Ok(())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        configure(&mut guard.ctx)?;
        if build {
            pip_install(&mut guard.distro, &mut guard.ctx, 3, &self.0)?;
        }
        Ok(())
    }
    fn is_dependent_on(&self) -> Option<&str> {
        None
    }
}

fn parse_req_filename(line: &str) -> Option<&str> {
    let res = vec!["-r", "--requirement ", "--requirement=",
                   "-c", "--constraint ", "--constraint="];
    for prefix in res.iter() {
        if line.starts_with(prefix) {
            return Some(line[prefix.len()..].trim());
        }
    }
    return None;
}

fn version_req(hash: &mut Digest, fname: &Path, used: &mut HashSet<String>) ->
               Result<(), VersionError> {

    let path = Path::new("/work").join(fname).canonicalize()
                   .map_err(|e| VersionError::Io(e, fname.to_path_buf()))?;

    let name = format!("{:?}", path);
    if used.contains(&name[..]) {
        return Err(VersionError::String(
            format!("Cyclic requirement: {}", name)))
    }

    used.insert(name);

    let f = File::open(&path).map_err(|e| VersionError::Io(e, path.clone()))?;

    let f = BufReader::new(f);
    for line in f.lines() {
        let line = line.map_err(|e| VersionError::Io(e, path.clone()))?;
        let chunk = line[..].trim();
        // Ignore empty lines and comments
        if chunk.len() == 0 || chunk.starts_with("#") {
            continue;
        }
        if let Some(req) = parse_req_filename(chunk) {
            version_req(hash, &fname.parent().unwrap().join(req), used)?;
            continue;
        }
        // Should we also ignore the order?
        hash.field("line", chunk);
    }
    Ok(())
}

impl BuildStep for Py2Requirements {
    fn name(&self) -> &'static str { "Py2Requirements" }
    fn hash(&self, _cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        version_req(hash, &self.0, &mut HashSet::new())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        configure(&mut guard.ctx)?;
        if build {
            pip_requirements(&mut guard.distro, &mut guard.ctx, 2, &self.0)?;
        }
        Ok(())
    }
    fn is_dependent_on(&self) -> Option<&str> {
        None
    }
}

impl BuildStep for Py3Requirements {
    fn name(&self) -> &'static str { "Py3Requirements" }
    fn hash(&self, _cfg: &Config, hash: &mut Digest)
        -> Result<(), VersionError>
    {
        version_req(hash, &self.0, &mut HashSet::new())
    }
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        configure(&mut guard.ctx)?;
        if build {
            pip_requirements(&mut guard.distro, &mut guard.ctx, 3, &self.0)?;
        }
        Ok(())
    }
    fn is_dependent_on(&self) -> Option<&str> {
        None
    }
}
<|endoftext|>


<commit_before>use std::ffi::{OsString, OsStr};
use std::path::Path;

use core::Source;
use sources::PathSource;
use ops::{self, ExecEngine, ProcessEngine, Compilation};
use util::{self, CargoResult, ProcessError, process_error};

pub struct TestOptions<'a> {
    pub compile_opts: ops::CompileOptions<'a>,
    pub no_run: bool,
    pub no_fail_fast: bool,
}

#[allow(deprecated)] // connect => join in 1.3
pub fn run_tests(manifest_path: &Path,
                 options: &TestOptions,
                 test_args: &[String]) -> CargoResult<Option<ProcessError>> {
    let config = options.compile_opts.config;
    let (compile, error) = try!(build_and_run(manifest_path, options, test_args));

    // If we have an error and want to fail fast, return
    if error.is_some() && !options.no_fail_fast {
        return Ok(error)
    }
    // If a specific test was requested or we're not running any tests at all,
    // don't run any doc tests.
    if let ops::CompileFilter::Only { .. } = options.compile_opts.filter {
        return Ok(None)
    }
    if options.no_run {
        return Ok(None)
    }

    let libs = compile.package.targets().iter()
                      .filter(|t| t.doctested())
                      .map(|t| (t.src_path(), t.name(), t.crate_name()));

    let mut process_errors = match error {
        None => Vec::new(),
        Some(err) => vec![err],
    };
    for (lib, name, crate_name) in libs {
        try!(config.shell().status("Doc-tests", name));
        let mut p = try!(compile.rustdoc_process(&compile.package));
        p.arg("--test").arg(lib)
         .arg("--crate-name").arg(&crate_name)
         .cwd(compile.package.root());

        for &rust_dep in &[&compile.deps_output, &compile.root_output] {
            let mut arg = OsString::from("dependency=");
            arg.push(rust_dep);
            p.arg("-L").arg(arg);
        }
        for native_dep in compile.native_dirs.values() {
            p.arg("-L").arg(native_dep);
        }

        if test_args.len() > 0 {
            p.arg("--test-args").arg(&test_args.connect(" "));
        }

        for feat in compile.features.iter() {
            p.arg("--cfg").arg(&format!("feature=\"{}\"", feat));
        }

        for (_, libs) in compile.libraries.iter() {
            for &(ref target, ref lib) in libs.iter() {
                // Note that we can *only* doctest rlib outputs here.  A
                // staticlib output cannot be linked by the compiler (it just
                // doesn't do that). A dylib output, however, can be linked by
                // the compiler, but will always fail. Currently all dylibs are
                // built as "static dylibs" where the standard library is
                // statically linked into the dylib. The doc tests fail,
                // however, for now as they try to link the standard library
                // dynamically as well, causing problems. As a result we only
                // pass `--extern` for rlib deps and skip out on all other
                // artifacts.
                if lib.extension() != Some(OsStr::new("rlib")) &&
                   !target.for_host() {
                    continue
                }
                let mut arg = OsString::from(target.crate_name());
                arg.push("=");
                arg.push(lib);
                p.arg("--extern").arg(&arg);
            }
        }

        try!(config.shell().verbose(|shell| {
            shell.status("Running", p.to_string())
        }));
        if let Err(e) = ExecEngine::exec(&mut ProcessEngine, p) {
            process_errors.push(e);
            if !options.no_fail_fast {
                break
            }
        }
    }
    if process_errors.is_empty() {
        Ok(None)
    } else if process_errors.len() == 1 {
        Ok(Some(process_errors.pop().unwrap()))
    } else {
        let err = process_error("Multiple tests failed", None, process_errors[0].exit.as_ref(), process_errors[0].output.as_ref());
        Ok(Some(err))
    }

}

pub fn run_benches(manifest_path: &Path,
                   options: &TestOptions,
                   args: &[String]) -> CargoResult<Option<ProcessError>> {
    let mut args = args.to_vec();
    args.push("--bench".to_string());

    match try!(build_and_run(manifest_path, options, &args)).1 {
        Some(err) => Ok(Some(err)),
        None => Ok(None)
    }
}

// This function always has to return the Compilation, regardless of errors.
// Otherwise --no-fail-fast is not possible.
fn build_and_run<'a>(manifest_path: &Path,
                     options: &TestOptions<'a>,
                     test_args: &[String])
                     -> CargoResult<(Compilation<'a>, Option<ProcessError>)> {
    let config = options.compile_opts.config;
    let mut source = try!(PathSource::for_path(&manifest_path.parent().unwrap(),
                                               config));
    try!(source.update());

    let mut compile = try!(ops::compile(manifest_path, &options.compile_opts));
    if options.no_run { return Ok((compile, None)) }
    compile.tests.sort();

    let cwd = config.cwd();
    let mut errors = Vec::new();
    for &(_, ref exe) in &compile.tests {
        let to_display = match util::without_prefix(exe, &cwd) {
            Some(path) => path,
            None => &**exe,
        };
        let mut cmd = try!(compile.target_process(exe, &compile.package));
        cmd.args(test_args);
        try!(config.shell().concise(|shell| {
            shell.status("Running", to_display.display().to_string())
        }));
        try!(config.shell().verbose(|shell| {
            shell.status("Running", cmd.to_string())
        }));

        if let Err(e) = ExecEngine::exec(&mut ProcessEngine, cmd) {
            errors.push(e);
            if !options.no_fail_fast {
                break
            }
        }
    }
    if errors.is_empty() {
        Ok((compile, None))
    } else if errors.len() == 1 {
        // Just one error occured => we can return it.
        Ok((compile, Some(errors.pop().unwrap())))
    } else {
        // Multiple tests failed => Create a more generic error
        let err = process_error("Multiple tests failed", None, errors[0].exit.as_ref(), errors[0].output.as_ref());
        Ok((compile, Some(err)))
    }
}
<commit_msg>Reformat lines with more than 100 characters<commit_after>use std::ffi::{OsString, OsStr};
use std::path::Path;

use core::Source;
use sources::PathSource;
use ops::{self, ExecEngine, ProcessEngine, Compilation};
use util::{self, CargoResult, ProcessError, process_error};

pub struct TestOptions<'a> {
    pub compile_opts: ops::CompileOptions<'a>,
    pub no_run: bool,
    pub no_fail_fast: bool,
}

#[allow(deprecated)] // connect => join in 1.3
pub fn run_tests(manifest_path: &Path,
                 options: &TestOptions,
                 test_args: &[String]) -> CargoResult<Option<ProcessError>> {
    let config = options.compile_opts.config;
    let (compile, error) = try!(build_and_run(manifest_path, options, test_args));

    // If we have an error and want to fail fast, return
    if error.is_some() && !options.no_fail_fast {
        return Ok(error)
    }
    // If a specific test was requested or we're not running any tests at all,
    // don't run any doc tests.
    if let ops::CompileFilter::Only { .. } = options.compile_opts.filter {
        return Ok(None)
    }
    if options.no_run {
        return Ok(None)
    }

    let libs = compile.package.targets().iter()
                      .filter(|t| t.doctested())
                      .map(|t| (t.src_path(), t.name(), t.crate_name()));

    let mut process_errors = match error {
        None => Vec::new(),
        Some(err) => vec![err],
    };
    for (lib, name, crate_name) in libs {
        try!(config.shell().status("Doc-tests", name));
        let mut p = try!(compile.rustdoc_process(&compile.package));
        p.arg("--test").arg(lib)
         .arg("--crate-name").arg(&crate_name)
         .cwd(compile.package.root());

        for &rust_dep in &[&compile.deps_output, &compile.root_output] {
            let mut arg = OsString::from("dependency=");
            arg.push(rust_dep);
            p.arg("-L").arg(arg);
        }
        for native_dep in compile.native_dirs.values() {
            p.arg("-L").arg(native_dep);
        }

        if test_args.len() > 0 {
            p.arg("--test-args").arg(&test_args.connect(" "));
        }

        for feat in compile.features.iter() {
            p.arg("--cfg").arg(&format!("feature=\"{}\"", feat));
        }

        for (_, libs) in compile.libraries.iter() {
            for &(ref target, ref lib) in libs.iter() {
                // Note that we can *only* doctest rlib outputs here.  A
                // staticlib output cannot be linked by the compiler (it just
                // doesn't do that). A dylib output, however, can be linked by
                // the compiler, but will always fail. Currently all dylibs are
                // built as "static dylibs" where the standard library is
                // statically linked into the dylib. The doc tests fail,
                // however, for now as they try to link the standard library
                // dynamically as well, causing problems. As a result we only
                // pass `--extern` for rlib deps and skip out on all other
                // artifacts.
                if lib.extension() != Some(OsStr::new("rlib")) &&
                   !target.for_host() {
                    continue
                }
                let mut arg = OsString::from(target.crate_name());
                arg.push("=");
                arg.push(lib);
                p.arg("--extern").arg(&arg);
            }
        }

        try!(config.shell().verbose(|shell| {
            shell.status("Running", p.to_string())
        }));
        if let Err(e) = ExecEngine::exec(&mut ProcessEngine, p) {
            process_errors.push(e);
            if !options.no_fail_fast {
                break
            }
        }
    }
    if process_errors.is_empty() {
        Ok(None)
    } else if process_errors.len() == 1 {
        Ok(Some(process_errors.pop().unwrap()))
    } else {
        let err = process_error("Multiple tests failed",
                                None,
                                process_errors[0].exit.as_ref(),
                                process_errors[0].output.as_ref());
        Ok(Some(err))
    }

}

pub fn run_benches(manifest_path: &Path,
                   options: &TestOptions,
                   args: &[String]) -> CargoResult<Option<ProcessError>> {
    let mut args = args.to_vec();
    args.push("--bench".to_string());

    match try!(build_and_run(manifest_path, options, &args)).1 {
        Some(err) => Ok(Some(err)),
        None => Ok(None)
    }
}

// This function always has to return the Compilation, regardless of errors.
// Otherwise --no-fail-fast is not possible.
fn build_and_run<'a>(manifest_path: &Path,
                     options: &TestOptions<'a>,
                     test_args: &[String])
                     -> CargoResult<(Compilation<'a>, Option<ProcessError>)> {
    let config = options.compile_opts.config;
    let mut source = try!(PathSource::for_path(&manifest_path.parent().unwrap(),
                                               config));
    try!(source.update());

    let mut compile = try!(ops::compile(manifest_path, &options.compile_opts));
    if options.no_run { return Ok((compile, None)) }
    compile.tests.sort();

    let cwd = config.cwd();
    let mut errors = Vec::new();
    for &(_, ref exe) in &compile.tests {
        let to_display = match util::without_prefix(exe, &cwd) {
            Some(path) => path,
            None => &**exe,
        };
        let mut cmd = try!(compile.target_process(exe, &compile.package));
        cmd.args(test_args);
        try!(config.shell().concise(|shell| {
            shell.status("Running", to_display.display().to_string())
        }));
        try!(config.shell().verbose(|shell| {
            shell.status("Running", cmd.to_string())
        }));

        if let Err(e) = ExecEngine::exec(&mut ProcessEngine, cmd) {
            errors.push(e);
            if !options.no_fail_fast {
                break
            }
        }
    }
    if errors.is_empty() {
        Ok((compile, None))
    } else if errors.len() == 1 {
        // Just one error occured => we can return it.
        Ok((compile, Some(errors.pop().unwrap())))
    } else {
        // Multiple tests failed => Create a more generic error
        let err = process_error("Multiple tests failed",
                                None,
                                errors[0].exit.as_ref(),
                                errors[0].output.as_ref());
        Ok((compile, Some(err)))
    }
}
<|endoftext|>


<commit_before>use codegen::RustWriter;
use std::io;
use std::str;
mod codegen;

struct Grammar {
	rules: ~[~Rule]
}

enum Item {
	Rule
}

struct Rule {
	name: ~str,
	expr: ~Expr,
	ret_type: ~str,
}

enum Attr {
	AttrDefineParser(~str),
	AttrDefineType(~str)
}

struct CharSetCase {
	start: char,
	end: char
}

struct TaggedExpr {
	name: Option<~str>,
	expr: ~Expr
}

enum Expr {
	AnyCharExpr,
	LiteralExpr(~str),
	CharSetExpr(bool, ~[CharSetCase]),
	RuleExpr(~str),
	SequenceExpr(~[~Expr]),
	ChoiceExpr(~[~Expr]),
	OptionalExpr(~Expr),
	ZeroOrMore(~Expr),
	OneOrMore(~Expr),
	DelimitedExpr(~Expr, ~Expr),
	PosAssertExpr(~Expr),
	NegAssertExpr(~Expr),
	StringifyExpr(~Expr),
	ActionExpr(~[TaggedExpr], ~str),
}

fn compile_grammar(w: &RustWriter, grammar: &Grammar) {
	compile_header(w);

	for rule in grammar.rules.iter() {
		compile_rule(w, *rule);
	}
}

fn compile_header(w: &RustWriter) {
	w.write("// Generated by rust-peg. Do not edit.
extern mod std;
use std::str::{CharRange};

#[inline]
fn slice_eq(input: &str, pos: uint, m: &str) -> Result<(uint, ()), uint> {
    let l = m.len();
    if (input.len() >= pos + l && input.slice(pos, pos+l) == m) {
        Ok((pos+l, ()))
    } else {
        Err(pos)
    }
}

#[inline]
fn any_char(input: &str, pos: uint) -> Result<(uint, ()), uint> {
    if input.len() > pos {
        Ok((input.char_range_at(pos).next, ()))
    } else {
        Err(pos)
    }
}
");
}

fn compile_rule(w: &RustWriter, rule: &Rule) {
	do w.def_fn(false, "parse_"+rule.name, "input: &str, pos: uint", "Result<(uint, " + rule.ret_type + ") , uint>") {
		compile_expr(w, rule.expr);
	}

	do w.def_fn(true, rule.name, "input: &str", "Result<"+rule.ret_type+", ~str>") {
		do w.match_block("parse_"+rule.name+"(input, 0)") {
			do w.match_case("Ok((pos, value))") {
				w.if_else("pos == input.len()",
					|| { w.line("Ok(value)"); },
					|| { w.line("Err(~\"Unexpected characters at end of input\")"); }
				)
			}
			w.match_inline_case("Err(pos)", "Err(\"Error at \"+ pos.to_str())");
		}
	}
}

fn compile_match_and_then(w: &RustWriter, e: &Expr, value_name: &str, then: &fn()) {
	do w.let_block("seq_res") {
		compile_expr(w, e);
	}
	do w.match_block("seq_res") {
		w.match_inline_case("Err(pos)", "Err(pos)");
		do w.match_case("Ok((pos, "+value_name+"))") {
			then();
		}
	}
}

fn compile_zero_or_more(w: &RustWriter, e: &Expr) {
	w.let_mut_stmt("repeat_pos", "pos");
	do w.loop_block {
		do w.let_block("step_res") {
			w.let_stmt("pos", "repeat_pos");
			compile_expr(w, e);
		}
		do w.match_block("step_res") {
			do w.match_case("Ok((newpos, value))") {
				w.line("repeat_pos = newpos;");
			}
			do w.match_case("Err(*)") {
				w.line("break;");
			}
		}
	}
	w.line("Ok((repeat_pos,()))");
}

fn compile_expr(w: &RustWriter, e: &Expr) {
	match *e {
		AnyCharExpr => {
			w.line("any_char(input, pos)");
			/*w.if_else("input.len() > pos",
				||{ w.line("Ok(pos+1)"); },
				||{ w.line("Err(pos)"); }
			);*/
		}

		LiteralExpr(ref s) => {
			w.line("slice_eq(input, pos, \""+*s+"\")");
			/*w.if_else("slice_eq(input, pos, \""+*s+"\")",
				||{ w.line("Ok(pos+" + s.len().to_str() + ")"); },
				||{ w.line("Err(pos)"); }
			);*/
		}

		CharSetExpr(invert, ref cases) => {
			w.if_else("input.len() > pos",
				|| {
					w.line("let CharRange {ch, next} = input.char_range_at(pos);");
					do w.match_block("ch") {
						w.write_indent();
						for (i, case) in cases.iter().enumerate() {
							if i != 0 { w.write(" | "); }
							if case.start == case.end {
								w.write("'"+str::from_char(case.start)+"'");
							} else {
								w.write("'"+str::from_char(case.start)+"'..'"+str::from_char(case.end)+"'");
							}
						}
						w.write(" => { Ok((next, ())) }\n");
						w.match_inline_case("_", "Err(pos)");
					}
				},
				|| { w.line("Err(pos)"); }
			)
		}

		RuleExpr(ref ruleName) => {
			w.line("parse_"+*ruleName+"(input, pos)");
		}

		SequenceExpr(ref exprs) => {
			fn write_seq(w: &RustWriter, exprs: &[~Expr]) {
				if (exprs.len() == 1) {
					compile_expr(w, exprs[0]);
				} else {
					do compile_match_and_then(w, exprs[0], "_") {
						write_seq(w, exprs.tail());
					}
				}
			}

			if (exprs.len() > 0 ) {
				write_seq(w, *exprs);
			}
		}

		ChoiceExpr(ref exprs) => {
			fn write_choice(w: &RustWriter, exprs: &[~Expr]) {
				if (exprs.len() == 1) {
					compile_expr(w, exprs[0]);
				} else {
					do w.let_block("choice_res") {
						compile_expr(w, exprs[0]);
					}
					do w.match_block("choice_res") {
						w.match_inline_case("Ok((pos, value))", "Ok((pos, value))");
						do w.match_case("Err(*)") {
							write_choice(w, exprs.tail());
						}
					}
				}
			}

			if (exprs.len() > 0 ) {
				write_choice(w, *exprs);
			}
		}

		OptionalExpr(ref e) => {
			do w.let_block("optional_res") {
				compile_expr(w, *e);
			}
			do w.match_block("optional_res") {
				w.match_inline_case("Ok((newpos, _))", "Ok((newpos, ()))");
				w.match_inline_case("Err(*)", "Ok((pos, ()))");
			}
		}

		ZeroOrMore(ref e) => {
			compile_zero_or_more(w, *e);
		}

		OneOrMore(ref e) => {
			do compile_match_and_then(w, *e, "_") {
				compile_zero_or_more(w, *e);
			}
		}

		DelimitedExpr(ref e, _) => fail!("not implemented"),

		  StringifyExpr(*)
		| PosAssertExpr(*)
		| NegAssertExpr(*) => fail!("not implemented"),

		ActionExpr(ref exprs, ref code) => {
			w.let_stmt("start_pos", "pos");
			fn write_seq(w: &RustWriter, exprs: &[TaggedExpr], code: &str) {
				if (exprs.len() > 0) {
					let name = match exprs.head().name {
						Some(ref s) => s.as_slice(),
						None => "_"
					};
					do compile_match_and_then(w, exprs.head().expr, name) {
						write_seq(w, exprs.tail(), code);
					}
				} else {
					w.write_indent();
					w.write("Ok((pos, (|| {");
					w.write(code);
					w.write("})()))\n");
				}
			}

			write_seq(w, *exprs, *code);
		}
	}
}

fn main() {
	let grammar = include!("grammar_def.rs");
	let w = RustWriter::new(io::stdout());
	compile_grammar(&w, grammar);
}<commit_msg>Support negated character classes<commit_after>use codegen::RustWriter;
use std::io;
use std::str;
mod codegen;

struct Grammar {
	rules: ~[~Rule]
}

enum Item {
	Rule
}

struct Rule {
	name: ~str,
	expr: ~Expr,
	ret_type: ~str,
}

enum Attr {
	AttrDefineParser(~str),
	AttrDefineType(~str)
}

struct CharSetCase {
	start: char,
	end: char
}

struct TaggedExpr {
	name: Option<~str>,
	expr: ~Expr
}

enum Expr {
	AnyCharExpr,
	LiteralExpr(~str),
	CharSetExpr(bool, ~[CharSetCase]),
	RuleExpr(~str),
	SequenceExpr(~[~Expr]),
	ChoiceExpr(~[~Expr]),
	OptionalExpr(~Expr),
	ZeroOrMore(~Expr),
	OneOrMore(~Expr),
	DelimitedExpr(~Expr, ~Expr),
	PosAssertExpr(~Expr),
	NegAssertExpr(~Expr),
	StringifyExpr(~Expr),
	ActionExpr(~[TaggedExpr], ~str),
}

fn compile_grammar(w: &RustWriter, grammar: &Grammar) {
	compile_header(w);

	for rule in grammar.rules.iter() {
		compile_rule(w, *rule);
	}
}

fn compile_header(w: &RustWriter) {
	w.write("// Generated by rust-peg. Do not edit.
extern mod std;
use std::str::{CharRange};

#[inline]
fn slice_eq(input: &str, pos: uint, m: &str) -> Result<(uint, ()), uint> {
    let l = m.len();
    if (input.len() >= pos + l && input.slice(pos, pos+l) == m) {
        Ok((pos+l, ()))
    } else {
        Err(pos)
    }
}

#[inline]
fn any_char(input: &str, pos: uint) -> Result<(uint, ()), uint> {
    if input.len() > pos {
        Ok((input.char_range_at(pos).next, ()))
    } else {
        Err(pos)
    }
}
");
}

fn compile_rule(w: &RustWriter, rule: &Rule) {
	do w.def_fn(false, "parse_"+rule.name, "input: &str, pos: uint", "Result<(uint, " + rule.ret_type + ") , uint>") {
		compile_expr(w, rule.expr);
	}

	do w.def_fn(true, rule.name, "input: &str", "Result<"+rule.ret_type+", ~str>") {
		do w.match_block("parse_"+rule.name+"(input, 0)") {
			do w.match_case("Ok((pos, value))") {
				w.if_else("pos == input.len()",
					|| { w.line("Ok(value)"); },
					|| { w.line("Err(~\"Unexpected characters at end of input\")"); }
				)
			}
			w.match_inline_case("Err(pos)", "Err(\"Error at \"+ pos.to_str())");
		}
	}
}

fn compile_match_and_then(w: &RustWriter, e: &Expr, value_name: &str, then: &fn()) {
	do w.let_block("seq_res") {
		compile_expr(w, e);
	}
	do w.match_block("seq_res") {
		w.match_inline_case("Err(pos)", "Err(pos)");
		do w.match_case("Ok((pos, "+value_name+"))") {
			then();
		}
	}
}

fn compile_zero_or_more(w: &RustWriter, e: &Expr) {
	w.let_mut_stmt("repeat_pos", "pos");
	do w.loop_block {
		do w.let_block("step_res") {
			w.let_stmt("pos", "repeat_pos");
			compile_expr(w, e);
		}
		do w.match_block("step_res") {
			do w.match_case("Ok((newpos, value))") {
				w.line("repeat_pos = newpos;");
			}
			do w.match_case("Err(*)") {
				w.line("break;");
			}
		}
	}
	w.line("Ok((repeat_pos,()))");
}

fn compile_expr(w: &RustWriter, e: &Expr) {
	match *e {
		AnyCharExpr => {
			w.line("any_char(input, pos)");
			/*w.if_else("input.len() > pos",
				||{ w.line("Ok(pos+1)"); },
				||{ w.line("Err(pos)"); }
			);*/
		}

		LiteralExpr(ref s) => {
			w.line("slice_eq(input, pos, \""+*s+"\")");
			/*w.if_else("slice_eq(input, pos, \""+*s+"\")",
				||{ w.line("Ok(pos+" + s.len().to_str() + ")"); },
				||{ w.line("Err(pos)"); }
			);*/
		}

		CharSetExpr(invert, ref cases) => {
			let result_strs = ("Ok((next, ()))", "Err(pos)");
			let (y_str, n_str) = if !invert { result_strs } else { result_strs.swap() };

			w.if_else("input.len() > pos",
				|| {
					w.line("let CharRange {ch, next} = input.char_range_at(pos);");
					do w.match_block("ch") {
						w.write_indent();
						for (i, case) in cases.iter().enumerate() {
							if i != 0 { w.write(" | "); }
							if case.start == case.end {
								w.write("'"+str::from_char(case.start)+"'");
							} else {
								w.write("'"+str::from_char(case.start)+"'..'"+str::from_char(case.end)+"'");
							}
						}
						w.write(" => { "+y_str+" }\n");
						w.match_inline_case("_", n_str);
					}
				},
				|| { w.line("Err(pos)"); }
			)
		}

		RuleExpr(ref ruleName) => {
			w.line("parse_"+*ruleName+"(input, pos)");
		}

		SequenceExpr(ref exprs) => {
			fn write_seq(w: &RustWriter, exprs: &[~Expr]) {
				if (exprs.len() == 1) {
					compile_expr(w, exprs[0]);
				} else {
					do compile_match_and_then(w, exprs[0], "_") {
						write_seq(w, exprs.tail());
					}
				}
			}

			if (exprs.len() > 0 ) {
				write_seq(w, *exprs);
			}
		}

		ChoiceExpr(ref exprs) => {
			fn write_choice(w: &RustWriter, exprs: &[~Expr]) {
				if (exprs.len() == 1) {
					compile_expr(w, exprs[0]);
				} else {
					do w.let_block("choice_res") {
						compile_expr(w, exprs[0]);
					}
					do w.match_block("choice_res") {
						w.match_inline_case("Ok((pos, value))", "Ok((pos, value))");
						do w.match_case("Err(*)") {
							write_choice(w, exprs.tail());
						}
					}
				}
			}

			if (exprs.len() > 0 ) {
				write_choice(w, *exprs);
			}
		}

		OptionalExpr(ref e) => {
			do w.let_block("optional_res") {
				compile_expr(w, *e);
			}
			do w.match_block("optional_res") {
				w.match_inline_case("Ok((newpos, _))", "Ok((newpos, ()))");
				w.match_inline_case("Err(*)", "Ok((pos, ()))");
			}
		}

		ZeroOrMore(ref e) => {
			compile_zero_or_more(w, *e);
		}

		OneOrMore(ref e) => {
			do compile_match_and_then(w, *e, "_") {
				compile_zero_or_more(w, *e);
			}
		}

		DelimitedExpr(ref e, _) => fail!("not implemented"),

		  StringifyExpr(*)
		| PosAssertExpr(*)
		| NegAssertExpr(*) => fail!("not implemented"),

		ActionExpr(ref exprs, ref code) => {
			w.let_stmt("start_pos", "pos");
			fn write_seq(w: &RustWriter, exprs: &[TaggedExpr], code: &str) {
				if (exprs.len() > 0) {
					let name = match exprs.head().name {
						Some(ref s) => s.as_slice(),
						None => "_"
					};
					do compile_match_and_then(w, exprs.head().expr, name) {
						write_seq(w, exprs.tail(), code);
					}
				} else {
					w.write_indent();
					w.write("Ok((pos, (|| {");
					w.write(code);
					w.write("})()))\n");
				}
			}

			write_seq(w, *exprs, *code);
		}
	}
}

fn main() {
	let grammar = include!("grammar_def.rs");
	let w = RustWriter::new(io::stdout());
	compile_grammar(&w, grammar);
}<|endoftext|>