<commit_before>#![no_std]
#![feature(lang_items)]

extern crate labrador_ldpc;

use labrador_ldpc::LDPCCode;
use labrador_ldpc::decoder::DecodeFrom;
use core::slice;

#[lang="eh_personality"] extern fn eh_personality() {}
#[lang="panic_fmt"] #[no_mangle] pub extern fn panic_fmt() { loop {}}

#[no_mangle]
pub extern fn labrador_ldpc_code_n(code: LDPCCode) -> usize {
    code.n()
}

#[no_mangle]
pub extern fn labrador_ldpc_code_k(code: LDPCCode) -> usize {
    code.k()
}

#[no_mangle]
pub extern fn labrador_ldpc_encode(code: LDPCCode, codeword: *mut u8) {
    if (codeword as usize) % 4 == 0 {
        let codeword: &mut[u32] = unsafe { slice::from_raw_parts_mut(codeword as *mut u32, code.n()/32) };
        code.encode(codeword);
    } else {
        let codeword: &mut[u8] = unsafe { slice::from_raw_parts_mut(codeword, code.n()/8) };
        code.encode(codeword);
    }
}

#[no_mangle]
pub extern fn labrador_ldpc_copy_encode(code: LDPCCode, data: *const u8, codeword: *mut u8) {
    let data: &[u8] = unsafe { slice::from_raw_parts(data, code.k()/8) };
    if (codeword as usize) % 4 == 0 {
        let codeword: &mut[u32] = unsafe { slice::from_raw_parts_mut(codeword as *mut u32, code.n()/32) };
        code.copy_encode(data, codeword);
    } else {
        let codeword: &mut[u8] = unsafe { slice::from_raw_parts_mut(codeword, code.n()/8) };
        code.copy_encode(data, codeword);
    }
}

#[no_mangle]
pub extern fn labrador_ldpc_bf_working_len(code: LDPCCode) -> usize {
    code.decode_bf_working_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_ms_working_len(code: LDPCCode) -> usize {
    code.decode_ms_working_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_ms_working_u8_len(code: LDPCCode) -> usize {
    code.decode_ms_working_u8_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_output_len(code: LDPCCode) -> usize {
    code.output_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_bf(code: LDPCCode, input: *const u8, output: *mut u8,
                                      working: *mut u8, max_iters: usize,
                                      iters_run: *mut usize) -> bool
{
    let input: &[u8] = unsafe { slice::from_raw_parts(input, code.n()/8) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.output_len()) };
    let working: &mut[u8] = unsafe { slice::from_raw_parts_mut(working, code.decode_bf_working_len()) };
    let (result, iters) = code.decode_bf(input, output, working, max_iters);
    if !iters_run.is_null() {
        unsafe { *iters_run = iters };
    }
    result
}

fn decode_ms<T: DecodeFrom>(code: LDPCCode, llrs: *const T, output: *mut u8, working: *mut T,
                            working_u8: *mut u8, max_iters: usize, iters_run: *mut usize) -> bool
{
    let llrs: &[T] = unsafe { slice::from_raw_parts(llrs, code.n()) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.output_len()) };
    let working: &mut[T] = unsafe { slice::from_raw_parts_mut(working, code.decode_ms_working_len()) };
    let working_u8: &mut[u8] = unsafe { slice::from_raw_parts_mut(working_u8, code.decode_ms_working_u8_len()) };
    let (result, iters) = code.decode_ms(llrs, output, working, working_u8, max_iters);
    if !iters_run.is_null() {
        unsafe { *iters_run = iters };
    }
    result
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_i8(code: LDPCCode, llrs: *const i8, output: *mut u8,
                                         working: *mut i8, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<i8>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_i16(code: LDPCCode, llrs: *const i16, output: *mut u8,
                                         working: *mut i16, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<i16>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_f32(code: LDPCCode, llrs: *const f32, output: *mut u8,
                                         working: *mut f32, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<f32>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_f64(code: LDPCCode, llrs: *const f64, output: *mut u8,
                                         working: *mut f64, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<f64>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

fn hard_to_llrs<T: DecodeFrom>(code: LDPCCode, input: *const u8, llrs: *mut T) {
    let input: &[u8] = unsafe { slice::from_raw_parts(input, code.n()/8) };
    let llrs: &mut[T] = unsafe { slice::from_raw_parts_mut(llrs, code.n()) };
    code.hard_to_llrs(input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_i8(code: LDPCCode, input: *const u8, llrs: *mut i8) {
    hard_to_llrs::<i8>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_i16(code: LDPCCode, input: *const u8, llrs: *mut i16) {
    hard_to_llrs::<i16>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_f32(code: LDPCCode, input: *const u8, llrs: *mut f32) {
    hard_to_llrs::<f32>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_f64(code: LDPCCode, input: *const u8, llrs: *mut f64) {
    hard_to_llrs::<f64>(code, input, llrs);
}

fn llrs_to_hard<T: DecodeFrom>(code: LDPCCode, llrs: *const T, output: *mut u8) {
    let llrs: &[T] = unsafe { slice::from_raw_parts(llrs, code.n()) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.n() / 8) };
    code.llrs_to_hard(llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_i8(code: LDPCCode, llrs: *const i8, output: *mut u8) {
    llrs_to_hard::<i8>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_i16(code: LDPCCode, llrs: *const i16, output: *mut u8) {
    llrs_to_hard::<i16>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_f32(code: LDPCCode, llrs: *const f32, output: *mut u8) {
    llrs_to_hard::<f32>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_f64(code: LDPCCode, llrs: *const f64, output: *mut u8) {
    llrs_to_hard::<f64>(code, llrs, output);
}
<commit_msg>panic_fmt -> panic_implementation<commit_after>#![no_std]
#![feature(panic_implementation)]

extern crate labrador_ldpc;

use labrador_ldpc::LDPCCode;
use labrador_ldpc::decoder::DecodeFrom;
use core::slice;
use core::panic::PanicInfo;

#[panic_implementation]
fn panic(_info: &PanicInfo) -> ! { loop {} }

#[no_mangle]
pub extern fn labrador_ldpc_code_n(code: LDPCCode) -> usize {
    code.n()
}

#[no_mangle]
pub extern fn labrador_ldpc_code_k(code: LDPCCode) -> usize {
    code.k()
}

#[no_mangle]
pub extern fn labrador_ldpc_encode(code: LDPCCode, codeword: *mut u8) {
    if (codeword as usize) % 4 == 0 {
        let codeword: &mut[u32] = unsafe { slice::from_raw_parts_mut(codeword as *mut u32, code.n()/32) };
        code.encode(codeword);
    } else {
        let codeword: &mut[u8] = unsafe { slice::from_raw_parts_mut(codeword, code.n()/8) };
        code.encode(codeword);
    }
}

#[no_mangle]
pub extern fn labrador_ldpc_copy_encode(code: LDPCCode, data: *const u8, codeword: *mut u8) {
    let data: &[u8] = unsafe { slice::from_raw_parts(data, code.k()/8) };
    if (codeword as usize) % 4 == 0 {
        let codeword: &mut[u32] = unsafe { slice::from_raw_parts_mut(codeword as *mut u32, code.n()/32) };
        code.copy_encode(data, codeword);
    } else {
        let codeword: &mut[u8] = unsafe { slice::from_raw_parts_mut(codeword, code.n()/8) };
        code.copy_encode(data, codeword);
    }
}

#[no_mangle]
pub extern fn labrador_ldpc_bf_working_len(code: LDPCCode) -> usize {
    code.decode_bf_working_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_ms_working_len(code: LDPCCode) -> usize {
    code.decode_ms_working_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_ms_working_u8_len(code: LDPCCode) -> usize {
    code.decode_ms_working_u8_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_output_len(code: LDPCCode) -> usize {
    code.output_len()
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_bf(code: LDPCCode, input: *const u8, output: *mut u8,
                                      working: *mut u8, max_iters: usize,
                                      iters_run: *mut usize) -> bool
{
    let input: &[u8] = unsafe { slice::from_raw_parts(input, code.n()/8) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.output_len()) };
    let working: &mut[u8] = unsafe { slice::from_raw_parts_mut(working, code.decode_bf_working_len()) };
    let (result, iters) = code.decode_bf(input, output, working, max_iters);
    if !iters_run.is_null() {
        unsafe { *iters_run = iters };
    }
    result
}

fn decode_ms<T: DecodeFrom>(code: LDPCCode, llrs: *const T, output: *mut u8, working: *mut T,
                            working_u8: *mut u8, max_iters: usize, iters_run: *mut usize) -> bool
{
    let llrs: &[T] = unsafe { slice::from_raw_parts(llrs, code.n()) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.output_len()) };
    let working: &mut[T] = unsafe { slice::from_raw_parts_mut(working, code.decode_ms_working_len()) };
    let working_u8: &mut[u8] = unsafe { slice::from_raw_parts_mut(working_u8, code.decode_ms_working_u8_len()) };
    let (result, iters) = code.decode_ms(llrs, output, working, working_u8, max_iters);
    if !iters_run.is_null() {
        unsafe { *iters_run = iters };
    }
    result
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_i8(code: LDPCCode, llrs: *const i8, output: *mut u8,
                                         working: *mut i8, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<i8>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_i16(code: LDPCCode, llrs: *const i16, output: *mut u8,
                                         working: *mut i16, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<i16>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_f32(code: LDPCCode, llrs: *const f32, output: *mut u8,
                                         working: *mut f32, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<f32>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

#[no_mangle]
pub extern fn labrador_ldpc_decode_ms_f64(code: LDPCCode, llrs: *const f64, output: *mut u8,
                                         working: *mut f64, working_u8: *mut u8, max_iters: usize,
                                         iters_run: *mut usize) -> bool
{
    decode_ms::<f64>(code, llrs, output, working, working_u8, max_iters, iters_run)
}

fn hard_to_llrs<T: DecodeFrom>(code: LDPCCode, input: *const u8, llrs: *mut T) {
    let input: &[u8] = unsafe { slice::from_raw_parts(input, code.n()/8) };
    let llrs: &mut[T] = unsafe { slice::from_raw_parts_mut(llrs, code.n()) };
    code.hard_to_llrs(input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_i8(code: LDPCCode, input: *const u8, llrs: *mut i8) {
    hard_to_llrs::<i8>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_i16(code: LDPCCode, input: *const u8, llrs: *mut i16) {
    hard_to_llrs::<i16>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_f32(code: LDPCCode, input: *const u8, llrs: *mut f32) {
    hard_to_llrs::<f32>(code, input, llrs);
}

#[no_mangle]
pub extern fn labrador_ldpc_hard_to_llrs_f64(code: LDPCCode, input: *const u8, llrs: *mut f64) {
    hard_to_llrs::<f64>(code, input, llrs);
}

fn llrs_to_hard<T: DecodeFrom>(code: LDPCCode, llrs: *const T, output: *mut u8) {
    let llrs: &[T] = unsafe { slice::from_raw_parts(llrs, code.n()) };
    let output: &mut[u8] = unsafe { slice::from_raw_parts_mut(output, code.n() / 8) };
    code.llrs_to_hard(llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_i8(code: LDPCCode, llrs: *const i8, output: *mut u8) {
    llrs_to_hard::<i8>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_i16(code: LDPCCode, llrs: *const i16, output: *mut u8) {
    llrs_to_hard::<i16>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_f32(code: LDPCCode, llrs: *const f32, output: *mut u8) {
    llrs_to_hard::<f32>(code, llrs, output);
}

#[no_mangle]
pub extern fn labrador_ldpc_llrs_to_hard_f64(code: LDPCCode, llrs: *const f64, output: *mut u8) {
    llrs_to_hard::<f64>(code, llrs, output);
}
<|endoftext|>


<commit_before>#![feature(slice_patterns)]
use std::env;
use std::fs::File;
use std::io::Read;
use std::collections::HashMap;

#[derive(Clone)]
enum Expr {
  Int(i64),
  Str(String)
}

// XXX this should probably be split up. The VM has the instructions, a "Thread" has locals, stack, and arguments.
struct VM<'a> {
  instructions: Vec<&'a str>,
  labels: HashMap<&'a str, usize>,
}

fn parse_labels<'a>(instructions: &Vec<&'a str>) -> HashMap<&'a str, usize> {
  let mut map = HashMap::new();
  for (i, instr) in instructions.iter().enumerate() {
    if instr.starts_with("$label") {
      match instr.split(' ').nth(1) {
        Some(label) => map.insert(label, i),
        None => panic!("VM error: missing label"),
      };
    }
  };
  map
}

impl<'a> VM<'a> {
  pub fn new(instructions: Vec<&'a str>) -> VM {
    VM {
      labels: parse_labels(&instructions),
      instructions: instructions,
    }
  }

  pub fn run(&mut self) {
    let ip = self.labels.get("main").unwrap_or(&0).clone();
    self.run_call(ip, &mut Vec::new());
  }

  // TODO locals
  pub fn run_call(&mut self, start_ip: usize, stack: &mut Vec<Expr>) -> Option<Expr> {
    let mut ip = start_ip;
    let len = self.instructions.len();
    let locals: &mut HashMap<&'a str, Expr> = &mut HashMap::new();

    let mut carry = false; // comparison carry

    let mut arguments = Vec::new();

    while ip < len {
      let instr = self.instructions[ip];
      ip += 1;
      if instr.starts_with("#") || instr.trim() == "" {
        continue;
      }
      match instr.split(" ").collect::<Vec<_>>().as_slice() {
        &["$label", _] => (),
        &["push", "int", n] => stack.push(Expr::Int(n.parse::<i64>().unwrap())),
        &["push", "str", n] => stack.push(Expr::Str(String::from(n))),
        &["push", "arg"] => arguments.push(stack.pop().expect("Nothing on the stack to push to the arguments")),

        &["dup"] => {
          let expr = stack.pop().expect("Nothing on the stack to pop");
          stack.push(expr.clone());
          stack.push(expr);
        },

        // how = "always" | "carry"
        &["jump", how, n] => {
          let new_ip = if n.starts_with("$") {
            self.labels.get(n.trim_matches('$')).expect("VM error: no such label").clone()
          } else {
            n.parse::<usize>().unwrap()
          };

          if new_ip < len {
            // only check carry if we are conditionally jumping
            if how == "always" || (how == "carry" && carry) {
              ip = new_ip;
            }
          } else {
            panic!("VM error: trying to jump past end of bytecode ({} > {})", new_ip, len);
          }
        },

        &["carry", "set", val] => carry = val == "true",
        &["carry", "invert"] => carry = !carry,

        &["call", "primitive", "say"] => if let Some(Expr::Str(arg)) = stack.pop() {
          println!("{}", arg);
        } else {
          panic!("VM error: incorrect arguments to `say`");
        },

        &["call", "primitive", "typeof"] => match stack.pop() {
            Some(Expr::Str(_)) => stack.push(Expr::Str(String::from("str"))),
            Some(Expr::Int(_)) => stack.push(Expr::Str(String::from("int"))),
            None => panic!("VM error: no argument supplied to `typeof`"),
        },

        &["call", "primitive", "convert"] => if let
            (Some(Expr::Str(from)), Some(Expr::Str(to)))
            =
            (stack.pop(), stack.pop()) {

            match (from.as_ref(), to.as_ref()) {
                ("int", "str") => if let Some(Expr::Int(arg)) = stack.pop() {
                  stack.push(Expr::Str(arg.to_string()));
                } else {
                  panic!("VM error: cannot convert int to string");
                },
                _ => panic!("VM error: cannot convert from {} to {}", from, to),
            }
        }
        else {
            panic!("VM error: bad arguments to primitive call `convert`");
        },

        // TODO resolve name in scope, check type, apply
        &["call", name] => {
          let new_ip = self.labels.get(name).expect("VM error: no such label").clone();
          let ret = self.run_call(new_ip, &mut arguments);
          arguments = Vec::new();
          match ret {
            Some(val) => stack.push(val),
            None => (),
          };
        },

        &["ret"] => {
          return None;
        },

        &["ret", "val"] => {
          if stack.len() != 1 {
            panic!("VM error: trying to return a value but the stack size is not 1 ({})", stack.len());
          }
          return stack.pop();
        },

        // NOTE: it's stack[*-1] OP stack[*-2]
        // which means if have stack=[1, 2]
        // you'll have 2 OP 1
        /// XXX this should JUST be a call!
        &["math", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (stack.pop(), stack.pop()) {
          let value = match op {
            "+" => arg1 + arg2,
            "-" => arg1 - arg2,
            //"/" => TODO. this should have very specific rules...
            "*" => arg1 * arg2,
            _ => panic!("VM error: unrecognized `op` operator: {}", op),
          };
          stack.push(Expr::Int(value));
        } else {
          panic!("VM error: not enough arguments to `math`");
        },

        // same note about "2 OP 1"
        // XXX same note about how this should be a `call`
        &["cmp", op] => carry = match (stack.pop(), stack.pop()) {
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2))) => match op {
                "<" => arg1 < arg2,
                ">" => arg1 > arg2,
                "<=" => arg1 <= arg2,
                ">=" => arg1 >= arg2,
                "=" => arg1 == arg2,
                _ => panic!("VM error: unrecognized `cmp` operator for int: {}", op),
            },
            (Some(Expr::Str(arg1)), Some(Expr::Str(arg2))) => match op {
                "=" => arg1 == arg2,
                _ => panic!("VM error: unrecognized `cmp` operator for str: {}", op),
            },
            _ => panic!("VM error: not enough arguments to `cmp`"),
        },

        // TODO this *shouldn't* be an identifier
        //      the backend should transform SSAF to tons of load/store
        //      (probably)
        //      (see backend#1)
        &["local", "load", name] => match locals.get(name) {
          Some(expr) => stack.push(expr.clone()),
          None       => panic!("VM error: unknown local variable {}", name),
        },

        &["local", "store", name] => if let Some(arg) = stack.pop() {
          // XXX check
          let _ = locals.insert(name, arg);
        } else {
          panic!("VM error: not enough arguments for `local store`");
        },

        &[instr, ..] => panic!("VM error: no such instruction {}", instr),
        &[..] => panic!("VM error: Unrecognized instruction!"),
      }
    }

    None
  }
}

fn main() {
	if let Some(path) = env::args().nth(1) {
		println!("Loading file {}", path);

    match File::open(&path) {
      Ok(mut file) => {
        let mut content = String::new();
        if let Ok(_) = file.read_to_string(&mut content) {
          // remove trailing newlines, split by line
          let instructions = content.trim_matches('\n').split('\n').collect();
          let mut vm = VM::new(instructions);
          vm.run();
        }
      },
      Err(err) => {
        panic!("Can't read file {} (error: {})", path, err);
      }
    }
	} else {
    panic!("Please give a file argument");
  }

  //     let path = Path::new("chry.fa");
  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //  print!("{}", line.unwrap());
  //      }
}
<commit_msg>Add multi-word string support<commit_after>#![feature(slice_patterns)]
use std::env;
use std::fs::File;
use std::io::Read;
use std::collections::HashMap;

#[derive(Clone)]
enum Expr {
  Int(i64),
  Str(String)
}

// XXX this should probably be split up. The VM has the instructions, a "Thread" has locals, stack, and arguments.
struct VM<'a> {
  instructions: Vec<&'a str>,
  labels: HashMap<&'a str, usize>,
}

fn parse_labels<'a>(instructions: &Vec<&'a str>) -> HashMap<&'a str, usize> {
  let mut map = HashMap::new();
  for (i, instr) in instructions.iter().enumerate() {
    if instr.starts_with("$label") {
      match instr.split(' ').nth(1) {
        Some(label) => map.insert(label, i),
        None => panic!("VM error: missing label"),
      };
    }
  };
  map
}

impl<'a> VM<'a> {
  pub fn new(instructions: Vec<&'a str>) -> VM {
    VM {
      labels: parse_labels(&instructions),
      instructions: instructions,
    }
  }

  pub fn run(&mut self) {
    let ip = self.labels.get("main").unwrap_or(&0).clone();
    self.run_call(ip, &mut Vec::new());
  }

  // TODO locals
  pub fn run_call(&mut self, start_ip: usize, stack: &mut Vec<Expr>) -> Option<Expr> {
    let mut ip = start_ip;
    let len = self.instructions.len();
    let locals: &mut HashMap<&'a str, Expr> = &mut HashMap::new();

    let mut carry = false; // comparison carry

    let mut arguments = Vec::new();

    while ip < len {
      let instr = self.instructions[ip];
      ip += 1;
      if instr.starts_with("#") || instr.trim() == "" {
        continue;
      }
      match instr.split(" ").collect::<Vec<_>>().as_slice() {
        &["$label", _] => (),
        &["push", "int", n] => stack.push(Expr::Int(n.parse::<i64>().unwrap())),
        &["push", "str", ref n..] => stack.push(Expr::Str(String::from(n.join(" ")))),
        &["push", "arg"] => arguments.push(stack.pop().expect("Nothing on the stack to push to the arguments")),

        &["dup"] => {
          let expr = stack.pop().expect("Nothing on the stack to pop");
          stack.push(expr.clone());
          stack.push(expr);
        },

        // how = "always" | "carry"
        &["jump", how, n] => {
          let new_ip = if n.starts_with("$") {
            self.labels.get(n.trim_matches('$')).expect("VM error: no such label").clone()
          } else {
            n.parse::<usize>().unwrap()
          };

          if new_ip < len {
            // only check carry if we are conditionally jumping
            if how == "always" || (how == "carry" && carry) {
              ip = new_ip;
            }
          } else {
            panic!("VM error: trying to jump past end of bytecode ({} > {})", new_ip, len);
          }
        },

        &["carry", "set", val] => carry = val == "true",
        &["carry", "invert"] => carry = !carry,

        &["call", "primitive", "say"] => if let Some(Expr::Str(arg)) = stack.pop() {
          println!("{}", arg);
        } else {
          panic!("VM error: incorrect arguments to `say`");
        },

        &["call", "primitive", "typeof"] => match stack.pop() {
            Some(Expr::Str(_)) => stack.push(Expr::Str(String::from("str"))),
            Some(Expr::Int(_)) => stack.push(Expr::Str(String::from("int"))),
            None => panic!("VM error: no argument supplied to `typeof`"),
        },

        &["call", "primitive", "convert"] => if let
            (Some(Expr::Str(from)), Some(Expr::Str(to)))
            =
            (stack.pop(), stack.pop()) {

            match (from.as_ref(), to.as_ref()) {
                ("int", "str") => if let Some(Expr::Int(arg)) = stack.pop() {
                  stack.push(Expr::Str(arg.to_string()));
                } else {
                  panic!("VM error: cannot convert int to string");
                },
                _ => panic!("VM error: cannot convert from {} to {}", from, to),
            }
        }
        else {
            panic!("VM error: bad arguments to primitive call `convert`");
        },

        // TODO resolve name in scope, check type, apply
        &["call", name] => {
          let new_ip = self.labels.get(name).expect("VM error: no such label").clone();
          let ret = self.run_call(new_ip, &mut arguments);
          arguments = Vec::new();
          match ret {
            Some(val) => stack.push(val),
            None => (),
          };
        },

        &["ret"] => {
          return None;
        },

        &["ret", "val"] => {
          if stack.len() != 1 {
            panic!("VM error: trying to return a value but the stack size is not 1 ({})", stack.len());
          }
          return stack.pop();
        },

        // NOTE: it's stack[*-1] OP stack[*-2]
        // which means if have stack=[1, 2]
        // you'll have 2 OP 1
        /// XXX this should JUST be a call!
        &["math", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (stack.pop(), stack.pop()) {
          let value = match op {
            "+" => arg1 + arg2,
            "-" => arg1 - arg2,
            //"/" => TODO. this should have very specific rules...
            "*" => arg1 * arg2,
            _ => panic!("VM error: unrecognized `op` operator: {}", op),
          };
          stack.push(Expr::Int(value));
        } else {
          panic!("VM error: not enough arguments to `math`");
        },

        // same note about "2 OP 1"
        // XXX same note about how this should be a `call`
        &["cmp", op] => carry = match (stack.pop(), stack.pop()) {
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2))) => match op {
                "<" => arg1 < arg2,
                ">" => arg1 > arg2,
                "<=" => arg1 <= arg2,
                ">=" => arg1 >= arg2,
                "=" => arg1 == arg2,
                _ => panic!("VM error: unrecognized `cmp` operator for int: {}", op),
            },
            (Some(Expr::Str(arg1)), Some(Expr::Str(arg2))) => match op {
                "=" => arg1 == arg2,
                _ => panic!("VM error: unrecognized `cmp` operator for str: {}", op),
            },
            _ => panic!("VM error: not enough arguments to `cmp`"),
        },

        // TODO this *shouldn't* be an identifier
        //      the backend should transform SSAF to tons of load/store
        //      (probably)
        //      (see backend#1)
        &["local", "load", name] => match locals.get(name) {
          Some(expr) => stack.push(expr.clone()),
          None       => panic!("VM error: unknown local variable {}", name),
        },

        &["local", "store", name] => if let Some(arg) = stack.pop() {
          // XXX check
          let _ = locals.insert(name, arg);
        } else {
          panic!("VM error: not enough arguments for `local store`");
        },

        &[instr, ..] => panic!("VM error: no such instruction {}", instr),
        &[..] => panic!("VM error: Unrecognized instruction!"),
      }
    }

    None
  }
}

fn main() {
	if let Some(path) = env::args().nth(1) {
		println!("Loading file {}", path);

    match File::open(&path) {
      Ok(mut file) => {
        let mut content = String::new();
        if let Ok(_) = file.read_to_string(&mut content) {
          // remove trailing newlines, split by line
          let instructions = content.trim_matches('\n').split('\n').collect();
          let mut vm = VM::new(instructions);
          vm.run();
        }
      },
      Err(err) => {
        panic!("Can't read file {} (error: {})", path, err);
      }
    }
	} else {
    panic!("Please give a file argument");
  }

  //     let path = Path::new("chry.fa");
  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //  print!("{}", line.unwrap());
  //      }
}
<|endoftext|>


<commit_before>extern crate libc;

use array::Array;
use defines::{AfError, SparseFormat};
use error::HANDLE_ERROR;
use self::libc::{uint8_t, c_void, c_int};
use util::{AfArray, DimT, HasAfEnum, MutAfArray, MutDimT};

#[allow(dead_code)]
extern {
    fn af_create_sparse_array(out: MutAfArray, nRows: DimT, nCols: DimT, vals: AfArray,
                              rowIdx: AfArray, colIdx: AfArray, stype: uint8_t) -> c_int;

    fn af_create_sparse_array_from_ptr(out: MutAfArray, nRows: DimT, nCols: DimT, nNZ: DimT,
                                       values: *const c_void, rowIdx: *const c_int, colIdx: *const c_int,
                                       aftype: uint8_t, stype: uint8_t, src: uint8_t) -> c_int;

    fn af_create_sparse_array_from_dense(out: MutAfArray, dense: AfArray, stype: uint8_t) -> c_int;

    fn af_sparse_convert_to(out: MutAfArray, input: AfArray, dstStrge: uint8_t) -> c_int;

    fn af_sparse_to_dense(out: MutAfArray, sparse: AfArray) -> c_int;

    fn af_sparse_get_info(vals: MutAfArray, rIdx: MutAfArray, cIdx: MutAfArray, stype: *mut uint8_t,
                          input: AfArray) -> c_int;

    fn af_sparse_get_values(out: MutAfArray, input: AfArray) -> c_int;

    fn af_sparse_get_row_idx(out: MutAfArray, input: AfArray) -> c_int;

    fn af_sparse_get_col_idx(out: MutAfArray, input: AfArray) -> c_int;

    fn af_sparse_get_nnz(out: MutDimT, input: AfArray) -> c_int;

    fn af_sparse_get_storage(out: *mut uint8_t, input: AfArray) -> c_int;
}

/// Create sprase matrix from arrays
///
/// This function converts [Array](./struct.Array.html) of `values` into sparse array
/// of `format` sparse format using arrays `row_indices` and `col_indices`.
///
/// # Parameters
///
/// - `rows` is the number of rows in the dense matrix
/// - `cols` is the number of columns in the dense matrix
/// - `values` is the \ref af::array containing the non-zero elements
///   `of the matrix
/// - `row_indices` is the row indices for the sparse array
/// - `col_indices` is the column indices for the sparse array
/// - `format` is the storage format of the sparse array
///
/// # Return Values
///
/// Array with data in given sparse format
///
/// # Note
///
/// This function only uses references of the input arrays to create the
/// sparse data structure and does not perform deep copies.
pub fn sparse(rows: u64, cols: u64, values: &Array, row_indices: &Array, col_indices: &Array,
              format: SparseFormat) -> Array {
    unsafe {
        let mut temp: i64 = 0;
        let err_val = af_create_sparse_array(&mut temp as MutAfArray, rows as DimT, cols as DimT,
                                             values.get() as AfArray, row_indices.get() as AfArray,
                                             col_indices.get() as AfArray, format as uint8_t);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(temp)
    }
}

/// Create sprase matrix from data on host memory
///
/// This function converts host array `values` into sparse array of `format` sparse
/// format using host arrays `row_indices` and `col_indices`.
///
/// # Parameters
///
/// - `rows` is the number of rows in the dense matrix
/// - `cols` is the number of columns in the dense matrix
/// - `nzz` is the number of non zero elements in the dense matrix
/// - `values` is the \ref af::array containing the non-zero elements
///   `of the matrix
/// - `row_indices` is the row indices for the sparse array
/// - `col_indices` is the column indices for the sparse array
/// - `format` is the storage format of the sparse array
///
/// # Return Values
///
/// Array with data in given sparse format
///
/// # Note
///
/// The rules for deep copy/shallow copy/reference are the same as for creating a
/// regular [Array](./struct.Array.html).
pub fn sparse_from_host<T: HasAfEnum>(rows: u64, cols: u64, nzz: u64,
                                     values: &[T], row_indices: &[i32], col_indices: &[i32],
                                     format: SparseFormat) -> Array {
    unsafe {
        let aftype = T::get_af_dtype();
        let mut temp: i64 = 0;
        let err_val = af_create_sparse_array_from_ptr(&mut temp as MutAfArray,
                                                      rows as DimT, cols as DimT, nzz as DimT,
                                                      values.as_ptr() as *const c_void,
                                                      row_indices.as_ptr() as *const c_int,
                                                      col_indices.as_ptr() as *const c_int,
                                                      aftype as uint8_t, format as uint8_t, 1);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(temp)
    }
}

/// Convert dense array to sparse array
///
/// # Parameters
///
/// - `dense` is the dense format array
/// - `format` is the target sparse format
///
/// # Return Values
///
/// Sparse Array
pub fn sparse_from_dense(dense: &Array, format: SparseFormat) -> Array {
    unsafe {
        let mut temp : i64 = 0;
        let err_val = af_create_sparse_array_from_dense(&mut temp as MutAfArray, dense.get() as AfArray,
                                                        format as uint8_t);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(temp)
    }
}

/// Convert between sparse formats
///
/// # Parameters
///
/// - `input` is the input sparse array
/// - `format` is the target sparse format
///
/// # Return Values
///
/// Sparse Array in targe sparse format.
pub fn sparse_convert_to(input: &Array, format: SparseFormat) -> Array {
    unsafe {
        let mut temp : i64 = 0;
        let err_val = af_sparse_convert_to(&mut temp as MutAfArray, input.get() as AfArray,
                                           format as uint8_t);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(temp)
    }
}

/// Convert sparse array to dense array
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Dense Array
pub fn sparse_to_dense(input: &Array) -> Array {
    unsafe {
        let mut temp : i64 = 0;
        let err_val = af_sparse_to_dense(&mut temp as MutAfArray, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(temp)
    }
}

/// Get sparse Array information
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// A tuple of values, row indices, coloumn indices Arrays and SparseFormat enum.
pub fn sparse_get_info(input: &Array) -> (Array, Array, Array, SparseFormat) {
    unsafe {
        let mut val : i64 = 0;
        let mut row : i64 = 0;
        let mut col : i64 = 0;
        let mut stype : u8 = 0;
        let err_val = af_sparse_get_info(&mut val as MutAfArray, &mut row as MutAfArray,
                                         &mut col as MutAfArray, &mut stype as *mut uint8_t,
                                         input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        (Array::from(val), Array::from(row), Array::from(col), SparseFormat::from(stype as i32))
    }
}

/// Get values of sparse Array
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Sparse array values
pub fn sparse_get_values(input: &Array) -> Array {
    unsafe {
        let mut val : i64 = 0;
        let err_val = af_sparse_get_values(&mut val as MutAfArray, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(val)
    }
}

/// Get row indices Array
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Array with row indices values of sparse Array
pub fn sparse_get_row_indices(input: &Array) -> Array {
    unsafe {
        let mut val : i64 = 0;
        let err_val = af_sparse_get_row_idx(&mut val as MutAfArray, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(val)
    }
}

/// Get cololumn indices Array
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Array with coloumn indices values of sparse Array
pub fn sparse_get_col_indices(input: &Array) -> Array {
    unsafe {
        let mut val : i64 = 0;
        let err_val = af_sparse_get_col_idx(&mut val as MutAfArray, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(val)
    }
}

/// Get number of non-zero elements in sparse array
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Number of non-zero elements of sparse Array
pub fn sparse_get_nnz(input: &Array) -> i64 {
    unsafe {
        let mut count : i64 = 0;
        let err_val = af_sparse_get_nnz(&mut count as *mut DimT, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        count
    }
}

/// Get sparse format
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Sparse array format
pub fn sparse_get_format(input: &Array) -> SparseFormat {
    unsafe {
        let mut stype : u8 = 0;
        let err_val = af_sparse_get_storage(&mut stype as *mut uint8_t, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        SparseFormat::from(stype as i32)
    }
}
<commit_msg>Fix Typo `Coloumn`<commit_after>extern crate libc;

use array::Array;
use defines::{AfError, SparseFormat};
use error::HANDLE_ERROR;
use self::libc::{uint8_t, c_void, c_int};
use util::{AfArray, DimT, HasAfEnum, MutAfArray, MutDimT};

#[allow(dead_code)]
extern {
    fn af_create_sparse_array(out: MutAfArray, nRows: DimT, nCols: DimT, vals: AfArray,
                              rowIdx: AfArray, colIdx: AfArray, stype: uint8_t) -> c_int;

    fn af_create_sparse_array_from_ptr(out: MutAfArray, nRows: DimT, nCols: DimT, nNZ: DimT,
                                       values: *const c_void, rowIdx: *const c_int, colIdx: *const c_int,
                                       aftype: uint8_t, stype: uint8_t, src: uint8_t) -> c_int;

    fn af_create_sparse_array_from_dense(out: MutAfArray, dense: AfArray, stype: uint8_t) -> c_int;

    fn af_sparse_convert_to(out: MutAfArray, input: AfArray, dstStrge: uint8_t) -> c_int;

    fn af_sparse_to_dense(out: MutAfArray, sparse: AfArray) -> c_int;

    fn af_sparse_get_info(vals: MutAfArray, rIdx: MutAfArray, cIdx: MutAfArray, stype: *mut uint8_t,
                          input: AfArray) -> c_int;

    fn af_sparse_get_values(out: MutAfArray, input: AfArray) -> c_int;

    fn af_sparse_get_row_idx(out: MutAfArray, input: AfArray) -> c_int;

    fn af_sparse_get_col_idx(out: MutAfArray, input: AfArray) -> c_int;

    fn af_sparse_get_nnz(out: MutDimT, input: AfArray) -> c_int;

    fn af_sparse_get_storage(out: *mut uint8_t, input: AfArray) -> c_int;
}

/// Create sprase matrix from arrays
///
/// This function converts [Array](./struct.Array.html) of `values` into sparse array
/// of `format` sparse format using arrays `row_indices` and `col_indices`.
///
/// # Parameters
///
/// - `rows` is the number of rows in the dense matrix
/// - `cols` is the number of columns in the dense matrix
/// - `values` is the \ref af::array containing the non-zero elements
///   `of the matrix
/// - `row_indices` is the row indices for the sparse array
/// - `col_indices` is the column indices for the sparse array
/// - `format` is the storage format of the sparse array
///
/// # Return Values
///
/// Array with data in given sparse format
///
/// # Note
///
/// This function only uses references of the input arrays to create the
/// sparse data structure and does not perform deep copies.
pub fn sparse(rows: u64, cols: u64, values: &Array, row_indices: &Array, col_indices: &Array,
              format: SparseFormat) -> Array {
    unsafe {
        let mut temp: i64 = 0;
        let err_val = af_create_sparse_array(&mut temp as MutAfArray, rows as DimT, cols as DimT,
                                             values.get() as AfArray, row_indices.get() as AfArray,
                                             col_indices.get() as AfArray, format as uint8_t);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(temp)
    }
}

/// Create sprase matrix from data on host memory
///
/// This function converts host array `values` into sparse array of `format` sparse
/// format using host arrays `row_indices` and `col_indices`.
///
/// # Parameters
///
/// - `rows` is the number of rows in the dense matrix
/// - `cols` is the number of columns in the dense matrix
/// - `nzz` is the number of non zero elements in the dense matrix
/// - `values` is the \ref af::array containing the non-zero elements
///   `of the matrix
/// - `row_indices` is the row indices for the sparse array
/// - `col_indices` is the column indices for the sparse array
/// - `format` is the storage format of the sparse array
///
/// # Return Values
///
/// Array with data in given sparse format
///
/// # Note
///
/// The rules for deep copy/shallow copy/reference are the same as for creating a
/// regular [Array](./struct.Array.html).
pub fn sparse_from_host<T: HasAfEnum>(rows: u64, cols: u64, nzz: u64,
                                     values: &[T], row_indices: &[i32], col_indices: &[i32],
                                     format: SparseFormat) -> Array {
    unsafe {
        let aftype = T::get_af_dtype();
        let mut temp: i64 = 0;
        let err_val = af_create_sparse_array_from_ptr(&mut temp as MutAfArray,
                                                      rows as DimT, cols as DimT, nzz as DimT,
                                                      values.as_ptr() as *const c_void,
                                                      row_indices.as_ptr() as *const c_int,
                                                      col_indices.as_ptr() as *const c_int,
                                                      aftype as uint8_t, format as uint8_t, 1);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(temp)
    }
}

/// Convert dense array to sparse array
///
/// # Parameters
///
/// - `dense` is the dense format array
/// - `format` is the target sparse format
///
/// # Return Values
///
/// Sparse Array
pub fn sparse_from_dense(dense: &Array, format: SparseFormat) -> Array {
    unsafe {
        let mut temp : i64 = 0;
        let err_val = af_create_sparse_array_from_dense(&mut temp as MutAfArray, dense.get() as AfArray,
                                                        format as uint8_t);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(temp)
    }
}

/// Convert between sparse formats
///
/// # Parameters
///
/// - `input` is the input sparse array
/// - `format` is the target sparse format
///
/// # Return Values
///
/// Sparse Array in targe sparse format.
pub fn sparse_convert_to(input: &Array, format: SparseFormat) -> Array {
    unsafe {
        let mut temp : i64 = 0;
        let err_val = af_sparse_convert_to(&mut temp as MutAfArray, input.get() as AfArray,
                                           format as uint8_t);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(temp)
    }
}

/// Convert sparse array to dense array
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Dense Array
pub fn sparse_to_dense(input: &Array) -> Array {
    unsafe {
        let mut temp : i64 = 0;
        let err_val = af_sparse_to_dense(&mut temp as MutAfArray, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(temp)
    }
}

/// Get sparse Array information
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// A tuple of values, row indices, column indices Arrays and SparseFormat enum.
pub fn sparse_get_info(input: &Array) -> (Array, Array, Array, SparseFormat) {
    unsafe {
        let mut val : i64 = 0;
        let mut row : i64 = 0;
        let mut col : i64 = 0;
        let mut stype : u8 = 0;
        let err_val = af_sparse_get_info(&mut val as MutAfArray, &mut row as MutAfArray,
                                         &mut col as MutAfArray, &mut stype as *mut uint8_t,
                                         input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        (Array::from(val), Array::from(row), Array::from(col), SparseFormat::from(stype as i32))
    }
}

/// Get values of sparse Array
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Sparse array values
pub fn sparse_get_values(input: &Array) -> Array {
    unsafe {
        let mut val : i64 = 0;
        let err_val = af_sparse_get_values(&mut val as MutAfArray, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(val)
    }
}

/// Get row indices Array
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Array with row indices values of sparse Array
pub fn sparse_get_row_indices(input: &Array) -> Array {
    unsafe {
        let mut val : i64 = 0;
        let err_val = af_sparse_get_row_idx(&mut val as MutAfArray, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(val)
    }
}

/// Get cololumn indices Array
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Array with coloumn indices values of sparse Array
pub fn sparse_get_col_indices(input: &Array) -> Array {
    unsafe {
        let mut val : i64 = 0;
        let err_val = af_sparse_get_col_idx(&mut val as MutAfArray, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        Array::from(val)
    }
}

/// Get number of non-zero elements in sparse array
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Number of non-zero elements of sparse Array
pub fn sparse_get_nnz(input: &Array) -> i64 {
    unsafe {
        let mut count : i64 = 0;
        let err_val = af_sparse_get_nnz(&mut count as *mut DimT, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        count
    }
}

/// Get sparse format
///
/// # Parameters
///
/// - `input` is the sparse array
///
/// # Return Values
///
/// Sparse array format
pub fn sparse_get_format(input: &Array) -> SparseFormat {
    unsafe {
        let mut stype : u8 = 0;
        let err_val = af_sparse_get_storage(&mut stype as *mut uint8_t, input.get() as AfArray);
        HANDLE_ERROR(AfError::from(err_val));
        SparseFormat::from(stype as i32)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 The predicates-rs Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use Predicate;

/// Predicate that checks for empty strings.
///
/// This is created by `predicates::str::is_empty`.
#[derive(Copy, Clone, Debug)]
pub struct IsEmptyPredicate {}

impl Predicate<str> for IsEmptyPredicate {
    fn eval(&self, variable: &str) -> bool {
        variable.is_empty()
    }
}

/// Creates a new `Predicate` that ensures a str is empty
///
/// # Examples
///
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::str::is_empty();
/// assert_eq!(true, predicate_fn.eval(""));
/// assert_eq!(false, predicate_fn.eval("Food World"));
/// ```
pub fn is_empty() -> IsEmptyPredicate {
    IsEmptyPredicate {}
}

#[derive(Copy, Clone, Debug)]
enum PatternOp {
    StartsWith,
    EndsWith,
    Contains,
}

/// Predicate that checks for patterns.
///
/// This is created by `predicates::str::{starts_with, ends_with, contains}`.
#[derive(Clone, Debug)]
pub struct PatternPredicate {
    pattern: String,
    op: PatternOp,
}

impl Predicate<str> for PatternPredicate {
    fn eval(&self, variable: &str) -> bool {
        match self.op {
            PatternOp::StartsWith => variable.starts_with(&self.pattern),
            PatternOp::EndsWith => variable.ends_with(&self.pattern),
            PatternOp::Contains => variable.contains(&self.pattern),
        }
    }
}

/// Creates a new `Predicate` that ensures a str starts with `pattern`
///
/// # Examples
///
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::str::starts_with("Hello");
/// assert_eq!(true, predicate_fn.eval("Hello World"));
/// assert_eq!(false, predicate_fn.eval("Goodbye World"));
/// ```
pub fn starts_with<P>(pattern: P) -> PatternPredicate
where
    P: Into<String>,
{
    PatternPredicate {
        pattern: pattern.into(),
        op: PatternOp::StartsWith,
    }
}

/// Creates a new `Predicate` that ensures a str ends with `pattern`
///
/// # Examples
///
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::str::ends_with("World");
/// assert_eq!(true, predicate_fn.eval("Hello World"));
/// assert_eq!(false, predicate_fn.eval("Hello Moon"));
/// ```
pub fn ends_with<P>(pattern: P) -> PatternPredicate
where
    P: Into<String>,
{
    PatternPredicate {
        pattern: pattern.into(),
        op: PatternOp::EndsWith,
    }
}

/// Creates a new `Predicate` that ensures a str contains `pattern`
///
/// # Examples
///
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::str::contains("Two");
/// assert_eq!(true, predicate_fn.eval("One Two Three"));
/// assert_eq!(false, predicate_fn.eval("Four Five Six"));
/// ```
pub fn contains<P>(pattern: P) -> PatternPredicate
where
    P: Into<String>,
{
    PatternPredicate {
        pattern: pattern.into(),
        op: PatternOp::Contains,
    }
}
<commit_msg>feat(str): Add contains(...).count<commit_after>// Copyright (c) 2018 The predicates-rs Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use Predicate;

/// Predicate that checks for empty strings.
///
/// This is created by `predicates::str::is_empty`.
#[derive(Copy, Clone, Debug)]
pub struct IsEmptyPredicate {}

impl Predicate<str> for IsEmptyPredicate {
    fn eval(&self, variable: &str) -> bool {
        variable.is_empty()
    }
}

/// Creates a new `Predicate` that ensures a str is empty
///
/// # Examples
///
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::str::is_empty();
/// assert_eq!(true, predicate_fn.eval(""));
/// assert_eq!(false, predicate_fn.eval("Food World"));
/// ```
pub fn is_empty() -> IsEmptyPredicate {
    IsEmptyPredicate {}
}

/// Predicate checks start of str
///
/// This is created by `predicates::str::starts_with`.
#[derive(Clone, Debug)]
pub struct StartsWithPredicate {
    pattern: String,
}

impl Predicate<str> for StartsWithPredicate {
    fn eval(&self, variable: &str) -> bool {
        variable.starts_with(&self.pattern)
    }
}

/// Creates a new `Predicate` that ensures a str starts with `pattern`
///
/// # Examples
///
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::str::starts_with("Hello");
/// assert_eq!(true, predicate_fn.eval("Hello World"));
/// assert_eq!(false, predicate_fn.eval("Goodbye World"));
/// ```
pub fn starts_with<P>(pattern: P) -> StartsWithPredicate
where
    P: Into<String>,
{
    StartsWithPredicate {
        pattern: pattern.into(),
    }
}

/// Predicate checks end of str
///
/// This is created by `predicates::str::ends_with`.
#[derive(Clone, Debug)]
pub struct EndsWithPredicate {
    pattern: String,
}

impl Predicate<str> for EndsWithPredicate {
    fn eval(&self, variable: &str) -> bool {
        variable.ends_with(&self.pattern)
    }
}

/// Creates a new `Predicate` that ensures a str ends with `pattern`
///
/// # Examples
///
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::str::ends_with("World");
/// assert_eq!(true, predicate_fn.eval("Hello World"));
/// assert_eq!(false, predicate_fn.eval("Hello Moon"));
/// ```
pub fn ends_with<P>(pattern: P) -> EndsWithPredicate
where
    P: Into<String>,
{
    EndsWithPredicate {
        pattern: pattern.into(),
    }
}

/// Predicate that checks for patterns.
///
/// This is created by `predicates::str:contains`.
#[derive(Clone, Debug)]
pub struct ContainsPredicate {
    pattern: String,
}

impl ContainsPredicate {
    /// Require a specific count of matches.
    ///
    /// # Examples
    ///
    /// ```
    /// use predicates::prelude::*;
    ///
    /// let predicate_fn = predicate::str::contains("Two").count(2);
    /// assert_eq!(true, predicate_fn.eval("One Two Three Two One"));
    /// assert_eq!(false, predicate_fn.eval("One Two Three"));
    /// ```
    pub fn count(self, count: usize) -> MatchesPredicate {
        MatchesPredicate {
            pattern: self.pattern,
            count,
        }
    }
}

impl Predicate<str> for ContainsPredicate {
    fn eval(&self, variable: &str) -> bool {
        variable.contains(&self.pattern)
    }
}

/// Predicate that checks for repeated patterns.
///
/// This is created by `predicates::str::contains(...).count`.
#[derive(Clone, Debug)]
pub struct MatchesPredicate {
    pattern: String,
    count: usize,
}

impl Predicate<str> for MatchesPredicate {
    fn eval(&self, variable: &str) -> bool {
        variable.matches(&self.pattern).count() == self.count
    }
}

/// Creates a new `Predicate` that ensures a str contains `pattern`
///
/// # Examples
///
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::str::contains("Two");
/// assert_eq!(true, predicate_fn.eval("One Two Three"));
/// assert_eq!(false, predicate_fn.eval("Four Five Six"));
/// ```
pub fn contains<P>(pattern: P) -> ContainsPredicate
where
    P: Into<String>,
{
    ContainsPredicate {
        pattern: pattern.into(),
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Types used to report parsing errors.

#![deny(missing_docs)]

use cssparser::{Parser, SourcePosition};
use log;
use stylesheets::UrlExtraData;

/// Errors that can be encountered while parsing CSS.
pub enum ParseError<'a> {
    /// A property declaration was not recognized.
    UnsupportedPropertyDeclaration(&'a str),
    /// A font face descriptor was not recognized.
    UnsupportedFontFaceDescriptor(&'a str),
    /// A keyframe rule was not valid.
    InvalidKeyframeRule(&'a str),
    /// A keyframe property declaration was not recognized.
    UnsupportedKeyframePropertyDeclaration(&'a str),
    /// A rule was invalid for some reason.
    InvalidRule(&'a str),
    /// A rule was not recognized.
    UnsupportedRule(&'a str),
    /// A viewport descriptor declaration was not recognized.
    UnsupportedViewportDescriptorDeclaration(&'a str),
    /// A counter style descriptor declaration was not recognized.
    UnsupportedCounterStyleDescriptorDeclaration(&'a str),
    /// A counter style rule had no symbols.
    InvalidCounterStyleWithoutSymbols(String),
    /// A counter style rule had less than two symbols.
    InvalidCounterStyleNotEnoughSymbols(String),
    /// A counter style rule did not have additive-symbols.
    InvalidCounterStyleWithoutAdditiveSymbols,
    /// A counter style rule had extends with symbols.
    InvalidCounterStyleExtendsWithSymbols,
    /// A counter style rule had extends with additive-symbols.
    InvalidCounterStyleExtendsWithAdditiveSymbols
}

impl<'a> ParseError<'a> {
    /// Turn a parse error into a string representation.
    pub fn to_string(&self) -> String {
        match *self {
            ParseError::UnsupportedPropertyDeclaration(decl) =>
                format!("Unsupported property declaration: '{}'", decl),
            ParseError::UnsupportedFontFaceDescriptor(decl) =>
                format!("Unsupported @font-face descriptor declaration: '{}'", decl),
            ParseError::InvalidKeyframeRule(rule) =>
                format!("Invalid keyframe rule: '{}'", rule),
            ParseError::UnsupportedKeyframePropertyDeclaration(decl) =>
                format!("Unsupported keyframe property declaration: '{}'", decl),
            ParseError::InvalidRule(rule) =>
                format!("Invalid rule: '{}'", rule),
            ParseError::UnsupportedRule(rule) =>
                format!("Unsupported rule: '{}'", rule),
            ParseError::UnsupportedViewportDescriptorDeclaration(decl) =>
                format!("Unsupported @viewport descriptor declaration: '{}'", decl),
            ParseError::UnsupportedCounterStyleDescriptorDeclaration(decl) =>
                format!("Unsupported @counter-style descriptor declaration: '{}'", decl),
            ParseError::InvalidCounterStyleWithoutSymbols(ref system) =>
                format!("Invalid @counter-style rule: 'system: {}' without 'symbols'", system),
            ParseError::InvalidCounterStyleNotEnoughSymbols(ref system) =>
                format!("Invalid @counter-style rule: 'system: {}' less than two 'symbols'", system),
            ParseError::InvalidCounterStyleWithoutAdditiveSymbols =>
                "Invalid @counter-style rule: 'system: additive' without 'additive-symbols'".into(),
            ParseError::InvalidCounterStyleExtendsWithSymbols =>
                "Invalid @counter-style rule: 'system: extends …' with 'symbols'".into(),
            ParseError::InvalidCounterStyleExtendsWithAdditiveSymbols =>
                "Invalid @counter-style rule: 'system: extends …' with 'additive-symbols'".into(),
        }
    }
}

/// A generic trait for an error reporter.
pub trait ParseErrorReporter : Sync + Send {
    /// Called when the style engine detects an error.
    ///
    /// Returns the current input being parsed, the source position it was
    /// reported from, and a message.
    fn report_error<'a>(&self,
                        input: &mut Parser,
                        position: SourcePosition,
                        error: ParseError<'a>,
                        url: &UrlExtraData,
                        line_number_offset: u64);
}

/// An error reporter that uses [the `log` crate](https://github.com/rust-lang-nursery/log)
/// at `info` level.
///
/// This logging is silent by default, and can be enabled with a `RUST_LOG=style=info`
/// environment variable.
/// (See [`env_logger`](https://rust-lang-nursery.github.io/log/env_logger/).)
pub struct RustLogReporter;

impl ParseErrorReporter for RustLogReporter {
    fn report_error<'a>(&self,
                        input: &mut Parser,
                        position: SourcePosition,
                        error: ParseError<'a>,
                        url: &UrlExtraData,
                        line_number_offset: u64) {
        if log_enabled!(log::LogLevel::Info) {
            let location = input.source_location(position);
            let line_offset = location.line + line_number_offset as usize;
            info!("Url:\t{}\n{}:{} {}", url.as_str(), line_offset, location.column, error.to_string())
        }
    }
}

/// Error reporter which silently forgets errors
pub struct NullReporter;

impl ParseErrorReporter for NullReporter {
    fn report_error<'a>(&self,
            _: &mut Parser,
            _: SourcePosition,
            _: ParseError<'a>,
            _: &UrlExtraData,
            _: u64) {
        // do nothing
    }
}

/// Create an instance of the default error reporter for Servo.
#[cfg(feature = "servo")]
pub fn create_error_reporter() -> RustLogReporter {
    RustLogReporter
}

/// Create an instance of the default error reporter for Stylo.
#[cfg(feature = "gecko")]
pub fn create_error_reporter() -> RustLogReporter {
    RustLogReporter
}
<commit_msg>The ParseErrorReporter trait no longer needs to be Send.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Types used to report parsing errors.

#![deny(missing_docs)]

use cssparser::{Parser, SourcePosition};
use log;
use stylesheets::UrlExtraData;

/// Errors that can be encountered while parsing CSS.
pub enum ParseError<'a> {
    /// A property declaration was not recognized.
    UnsupportedPropertyDeclaration(&'a str),
    /// A font face descriptor was not recognized.
    UnsupportedFontFaceDescriptor(&'a str),
    /// A keyframe rule was not valid.
    InvalidKeyframeRule(&'a str),
    /// A keyframe property declaration was not recognized.
    UnsupportedKeyframePropertyDeclaration(&'a str),
    /// A rule was invalid for some reason.
    InvalidRule(&'a str),
    /// A rule was not recognized.
    UnsupportedRule(&'a str),
    /// A viewport descriptor declaration was not recognized.
    UnsupportedViewportDescriptorDeclaration(&'a str),
    /// A counter style descriptor declaration was not recognized.
    UnsupportedCounterStyleDescriptorDeclaration(&'a str),
    /// A counter style rule had no symbols.
    InvalidCounterStyleWithoutSymbols(String),
    /// A counter style rule had less than two symbols.
    InvalidCounterStyleNotEnoughSymbols(String),
    /// A counter style rule did not have additive-symbols.
    InvalidCounterStyleWithoutAdditiveSymbols,
    /// A counter style rule had extends with symbols.
    InvalidCounterStyleExtendsWithSymbols,
    /// A counter style rule had extends with additive-symbols.
    InvalidCounterStyleExtendsWithAdditiveSymbols
}

impl<'a> ParseError<'a> {
    /// Turn a parse error into a string representation.
    pub fn to_string(&self) -> String {
        match *self {
            ParseError::UnsupportedPropertyDeclaration(decl) =>
                format!("Unsupported property declaration: '{}'", decl),
            ParseError::UnsupportedFontFaceDescriptor(decl) =>
                format!("Unsupported @font-face descriptor declaration: '{}'", decl),
            ParseError::InvalidKeyframeRule(rule) =>
                format!("Invalid keyframe rule: '{}'", rule),
            ParseError::UnsupportedKeyframePropertyDeclaration(decl) =>
                format!("Unsupported keyframe property declaration: '{}'", decl),
            ParseError::InvalidRule(rule) =>
                format!("Invalid rule: '{}'", rule),
            ParseError::UnsupportedRule(rule) =>
                format!("Unsupported rule: '{}'", rule),
            ParseError::UnsupportedViewportDescriptorDeclaration(decl) =>
                format!("Unsupported @viewport descriptor declaration: '{}'", decl),
            ParseError::UnsupportedCounterStyleDescriptorDeclaration(decl) =>
                format!("Unsupported @counter-style descriptor declaration: '{}'", decl),
            ParseError::InvalidCounterStyleWithoutSymbols(ref system) =>
                format!("Invalid @counter-style rule: 'system: {}' without 'symbols'", system),
            ParseError::InvalidCounterStyleNotEnoughSymbols(ref system) =>
                format!("Invalid @counter-style rule: 'system: {}' less than two 'symbols'", system),
            ParseError::InvalidCounterStyleWithoutAdditiveSymbols =>
                "Invalid @counter-style rule: 'system: additive' without 'additive-symbols'".into(),
            ParseError::InvalidCounterStyleExtendsWithSymbols =>
                "Invalid @counter-style rule: 'system: extends …' with 'symbols'".into(),
            ParseError::InvalidCounterStyleExtendsWithAdditiveSymbols =>
                "Invalid @counter-style rule: 'system: extends …' with 'additive-symbols'".into(),
        }
    }
}

/// A generic trait for an error reporter.
pub trait ParseErrorReporter : Sync {
    /// Called when the style engine detects an error.
    ///
    /// Returns the current input being parsed, the source position it was
    /// reported from, and a message.
    fn report_error<'a>(&self,
                        input: &mut Parser,
                        position: SourcePosition,
                        error: ParseError<'a>,
                        url: &UrlExtraData,
                        line_number_offset: u64);
}

/// An error reporter that uses [the `log` crate](https://github.com/rust-lang-nursery/log)
/// at `info` level.
///
/// This logging is silent by default, and can be enabled with a `RUST_LOG=style=info`
/// environment variable.
/// (See [`env_logger`](https://rust-lang-nursery.github.io/log/env_logger/).)
pub struct RustLogReporter;

impl ParseErrorReporter for RustLogReporter {
    fn report_error<'a>(&self,
                        input: &mut Parser,
                        position: SourcePosition,
                        error: ParseError<'a>,
                        url: &UrlExtraData,
                        line_number_offset: u64) {
        if log_enabled!(log::LogLevel::Info) {
            let location = input.source_location(position);
            let line_offset = location.line + line_number_offset as usize;
            info!("Url:\t{}\n{}:{} {}", url.as_str(), line_offset, location.column, error.to_string())
        }
    }
}

/// Error reporter which silently forgets errors
pub struct NullReporter;

impl ParseErrorReporter for NullReporter {
    fn report_error<'a>(&self,
            _: &mut Parser,
            _: SourcePosition,
            _: ParseError<'a>,
            _: &UrlExtraData,
            _: u64) {
        // do nothing
    }
}

/// Create an instance of the default error reporter for Servo.
#[cfg(feature = "servo")]
pub fn create_error_reporter() -> RustLogReporter {
    RustLogReporter
}

/// Create an instance of the default error reporter for Stylo.
#[cfg(feature = "gecko")]
pub fn create_error_reporter() -> RustLogReporter {
    RustLogReporter
}
<|endoftext|>


<commit_before>#[link(name="rm", vers="1.0.0", author="Arcterus")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern mod extra;

use std::os;
use std::io::{stderr,fs,io_error};
use extra::getopts::groups;

enum InteractiveMode {
    InteractiveNone,
    InteractiveOnce,
    InteractiveAlways
}

fn main() {
    let args = os::args();
    let program = args[0].clone();

    // TODO: make getopts support -R in addition to -r
    let opts = ~[
        groups::optflag("f", "force", "ignore nonexistent files and arguments, never prompt"),
        groups::optflag("i", "", "prompt before every removal"),
        groups::optflag("I", "", "prompt once before removing more than three files, or when removing recursively.  Less intrusive than -i, while still giving some protection against most mistakes"),
        groups::optflagopt("", "interactive", "prompt according to WHEN: never, once (-I), or always (-i).  Without WHEN, prompts always", "WHEN"),
        groups::optflag("", "one-file-system", "when removing a hierarchy recursively, skip any directory that is on a file system different from that of the corresponding command line argument"),
        groups::optflag("", "no-preserve-root", "do not treat '/' specially"),
        groups::optflag("", "preserve-root", "do not remove '/' (default)"),
        groups::optflag("r", "recursive", "remove directories and their contents recursively"),
        groups::optflag("d", "dir", "remove empty directories"),
        groups::optflag("v", "verbose", "explain what is being done"),
        groups::optflag("", "help", "display this help and exit"),
        groups::optflag("", "version", "output version information and exit")
    ];
    let matches = match groups::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut stderr() as &mut Writer,
                     "{}", f.to_err_msg());
            os::set_exit_status(1);
            return
        }
    };
    if matches.opt_present("help") {
        println("rm 1.0.0");
        println("");
        println("Usage:");
        println!("  {0:s} [OPTION]... [FILE]...", program);
        println("");
        print(groups::usage("Remove (unlink) the FILE(s).", opts));
        println("");
        println("By default, rm does not remove directories.  Use the --recursive (-r)");
        println("option to remove each listed directory, too, along with all of its contents");
        println("");
        println("To remove a file whose name starts with a '-', for example '-foo',");
        println("use one of these commands:");
        println("rm -- -foo");
        println("");
        println("rm ./-foo");
        println("");
        println("Note that if you use rm to remove a file, it might be possible to recover");
        println("some of its contents, given sufficient expertise and/or time.  For greater");
        println("assurance that the contents are truly unrecoverable, consider using shred.");
    } else if matches.opt_present("version") {
        println("rm 1.0.0");
    } else {
        let force = matches.opt_present("force");
        let interactive =
            if matches.opt_present("i") {
                InteractiveAlways
            } else if matches.opt_present("I") {
                InteractiveOnce
            } else if matches.opt_present("interactive") {
                match matches.opt_str("interactive").unwrap() {
                    ~"none" => InteractiveNone,
                    ~"once" => InteractiveOnce,
                    ~"always" => InteractiveAlways,
                    val => {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Invalid argument to interactive ({})", val);
                        os::set_exit_status(1);
                        return
                    }
                }
            } else {
                InteractiveNone
            };
        let one_fs = matches.opt_present("one-file-system");
        let preserve_root = !matches.opt_present("no-preserve-root");
        let recursive = matches.opt_present("recursive");
        let dir = matches.opt_present("dir");
        let verbose = matches.opt_present("verbose");
        remove_files(matches.free, force, interactive, one_fs, preserve_root,
                     recursive, dir, verbose);
    }
}

fn remove_files(files: &[~str], force: bool, interactive: InteractiveMode, one_fs: bool, preserve_root: bool, recursive: bool, dir: bool, verbose: bool) {
    for filename in files.iter() {
        let file = Path::new(filename.to_owned());
        if file.exists() {
            if file.is_dir() {
                if recursive && (*filename != ~"/" || !preserve_root) {
                    remove_files(fs::walk_dir(&file).map(|x| x.as_str().unwrap().to_owned()).to_owned_vec(), force, interactive, one_fs, preserve_root, recursive, dir, verbose);
                    io_error::cond.trap(|_| {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Could not remove directory: '{}'", *filename);
                    }).inside(|| {
                        fs::rmdir(&file);
                    });
                } else if dir {
                    io_error::cond.trap(|_| {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Could not remove directory '{}'", *filename);
                    }).inside(|| {
                        fs::rmdir(&file);
                    });
                } else {
                    writeln!(&mut stderr() as &mut Writer,
                             "Could not remove directory '{}' (did you mean to pass '-r'?)",
                             *filename);
                }
            } else {
                io_error::cond.trap(|_| {
                    writeln!(&mut stderr() as &mut Writer,
                             "Could not remove file: '{}'", *filename);
                    os::set_exit_status(1);
                }).inside(|| {
                    fs::unlink(&file);
                });
            }
        } else if !force {
            writeln!(&mut stderr() as &mut Writer,
                     "Invalid file: '{}'", *filename);
            os::set_exit_status(1);
        }
    }
}

<commit_msg>Add more '/' checks to rm<commit_after>#[link(name="rm", vers="1.0.0", author="Arcterus")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern mod extra;

use std::os;
use std::io::{stderr,fs,io_error};
use extra::getopts::groups;

enum InteractiveMode {
    InteractiveNone,
    InteractiveOnce,
    InteractiveAlways
}

fn main() {
    let args = os::args();
    let program = args[0].clone();

    // TODO: make getopts support -R in addition to -r
    let opts = ~[
        groups::optflag("f", "force", "ignore nonexistent files and arguments, never prompt"),
        groups::optflag("i", "", "prompt before every removal"),
        groups::optflag("I", "", "prompt once before removing more than three files, or when removing recursively.  Less intrusive than -i, while still giving some protection against most mistakes"),
        groups::optflagopt("", "interactive", "prompt according to WHEN: never, once (-I), or always (-i).  Without WHEN, prompts always", "WHEN"),
        groups::optflag("", "one-file-system", "when removing a hierarchy recursively, skip any directory that is on a file system different from that of the corresponding command line argument"),
        groups::optflag("", "no-preserve-root", "do not treat '/' specially"),
        groups::optflag("", "preserve-root", "do not remove '/' (default)"),
        groups::optflag("r", "recursive", "remove directories and their contents recursively"),
        groups::optflag("d", "dir", "remove empty directories"),
        groups::optflag("v", "verbose", "explain what is being done"),
        groups::optflag("", "help", "display this help and exit"),
        groups::optflag("", "version", "output version information and exit")
    ];
    let matches = match groups::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut stderr() as &mut Writer,
                     "{}", f.to_err_msg());
            os::set_exit_status(1);
            return
        }
    };
    if matches.opt_present("help") {
        println("rm 1.0.0");
        println("");
        println("Usage:");
        println!("  {0:s} [OPTION]... [FILE]...", program);
        println("");
        print(groups::usage("Remove (unlink) the FILE(s).", opts));
        println("");
        println("By default, rm does not remove directories.  Use the --recursive (-r)");
        println("option to remove each listed directory, too, along with all of its contents");
        println("");
        println("To remove a file whose name starts with a '-', for example '-foo',");
        println("use one of these commands:");
        println("rm -- -foo");
        println("");
        println("rm ./-foo");
        println("");
        println("Note that if you use rm to remove a file, it might be possible to recover");
        println("some of its contents, given sufficient expertise and/or time.  For greater");
        println("assurance that the contents are truly unrecoverable, consider using shred.");
    } else if matches.opt_present("version") {
        println("rm 1.0.0");
    } else {
        let force = matches.opt_present("force");
        let interactive =
            if matches.opt_present("i") {
                InteractiveAlways
            } else if matches.opt_present("I") {
                InteractiveOnce
            } else if matches.opt_present("interactive") {
                match matches.opt_str("interactive").unwrap() {
                    ~"none" => InteractiveNone,
                    ~"once" => InteractiveOnce,
                    ~"always" => InteractiveAlways,
                    val => {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Invalid argument to interactive ({})", val);
                        os::set_exit_status(1);
                        return
                    }
                }
            } else {
                InteractiveNone
            };
        let one_fs = matches.opt_present("one-file-system");
        let preserve_root = !matches.opt_present("no-preserve-root");
        let recursive = matches.opt_present("recursive");
        let dir = matches.opt_present("dir");
        let verbose = matches.opt_present("verbose");
        remove_files(matches.free, force, interactive, one_fs, preserve_root,
                     recursive, dir, verbose);
    }
}

fn remove_files(files: &[~str], force: bool, interactive: InteractiveMode, one_fs: bool, preserve_root: bool, recursive: bool, dir: bool, verbose: bool) {
    for filename in files.iter() {
        let file = Path::new(filename.to_owned());
        if file.exists() {
            if file.is_dir() {
                if recursive && (*filename != ~"/" || !preserve_root) {
                    remove_files(fs::walk_dir(&file).map(|x| x.as_str().unwrap().to_owned()).to_owned_vec(), force, interactive, one_fs, preserve_root, recursive, dir, verbose);
                    io_error::cond.trap(|_| {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Could not remove directory: '{}'", *filename);
                    }).inside(|| {
                        fs::rmdir(&file);
                    });
                } else if dir && (*filename != ~"/" || !preserve_root) {
                    io_error::cond.trap(|_| {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Could not remove directory '{}'", *filename);
                    }).inside(|| {
                        fs::rmdir(&file);
                    });
                } else {
                    if recursive {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Could not remove directory '{}'",
                                 *filename);
                    } else {
                        writeln!(&mut stderr() as &mut Writer,
                                 "Could not remove directory '{}' (did you mean to pass '-r'?)",
                                 *filename);
                    }
                }
            } else {
                io_error::cond.trap(|_| {
                    writeln!(&mut stderr() as &mut Writer,
                             "Could not remove file: '{}'", *filename);
                    os::set_exit_status(1);
                }).inside(|| {
                    fs::unlink(&file);
                });
            }
        } else if !force {
            writeln!(&mut stderr() as &mut Writer,
                     "Invalid file: '{}'", *filename);
            os::set_exit_status(1);
        }
    }
}

<|endoftext|>


<commit_before>use std::fmt;

pub trait XYPair {
    fn as_xy(&self) -> (int, int);
}

pub struct Point {
    x: int,
    y: int
}

impl Point {

    pub fn new(x: int, y: int) -> Point {
        Point { x: x, y: y }
    }

    pub fn zero() -> Point {
        Point { x: 0, y: 0 }
    }

    pub fn move_dir(&self, dir: Direction) -> Point {
        *self + dir.as_xy()
    }

}

impl Add<Point, Point> for Point {
    fn add(&self, other: &Point) -> Point {
        let (ox, oy) = other.as_xy();
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl Add<(int, int), Point> for Point {
    fn add(&self, other: &(int, int)) -> Point {
        let (ox, oy) = *other;
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl fmt::Show for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Point({}, {})", self.x, self.y)
    }
}

impl XYPair for Point {
    fn as_xy(&self) -> (int, int) {
        (self.x, self.y)
    }
}

pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl XYPair for Direction {
    fn as_xy(&self) -> (int, int) {
        match *self {
            Direction::Up      => (  0, -1),
            Direction::Down    => (  0,  1),
            Direction::Left    => ( -1,  0),
            Direction::Right   => (  1,  0),
        }
    }
}
<commit_msg>Implement copy for util::Point and change Add trait definitions<commit_after>use std::fmt;

pub trait XYPair {
    fn as_xy(&self) -> (int, int);
}

pub struct Point {
    x: int,
    y: int
}

impl Point {

    pub fn new(x: int, y: int) -> Point {
        Point { x: x, y: y }
    }

    pub fn zero() -> Point {
        Point { x: 0, y: 0 }
    }

    pub fn move_dir(&self, dir: Direction) -> Point {
        *self + dir.as_xy()
    }

}

impl Copy for Point {}

impl Add<Point, Point> for Point {
    fn add(self, other: Point) -> Point {
        let (ox, oy) : (int, int) = other.as_xy();
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl Add<(int, int), Point> for Point {
    fn add(self, other: (int, int)) -> Point {
        let (ox, oy) = other;
        Point { x: self.x + ox, y: self.y + oy }
    }
}

impl fmt::Show for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Point({}, {})", self.x, self.y)
    }
}

impl XYPair for Point {
    fn as_xy(&self) -> (int, int) {
        (self.x, self.y)
    }
}

pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl XYPair for Direction {
    fn as_xy(&self) -> (int, int) {
        match *self {
            Direction::Up      => (  0, -1),
            Direction::Down    => (  0,  1),
            Direction::Left    => ( -1,  0),
            Direction::Right   => (  1,  0),
        }
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate multibloom;
extern crate test;
extern crate rand;

use test::{Bencher, black_box};
use multibloom::BloomFilter;
use rand::Rng;

#[bench]
fn bench_add_1(b: &mut Bencher) {
    let mut bloom = BloomFilter::new(1000, 10);
    let bytes = rand::thread_rng().gen_iter::<u8>().take(1).collect::<Vec<u8>>();
    let testing = 100;
    b.iter(|| {
        bloom.add(&testing);
        black_box(&bloom);
    });
}

#[bench]
fn bench_add_64(b: &mut Bencher) {
    let mut bloom = BloomFilter::new(1000, 10);
    let bytes = rand::thread_rng().gen_iter::<u8>().take(64).collect::<Vec<u8>>();

    b.iter(|| {
        bloom.add(&bytes);
        black_box(&bloom);
    });
}

#[bench]
fn bench_add_1k(b: &mut Bencher) {
    let mut bloom = BloomFilter::new(1000, 10);
    let bytes = rand::thread_rng().gen_iter::<u8>().take(1024).collect::<Vec<u8>>();
    b.iter(|| {
        bloom.add(&bytes);
        black_box(&bloom);
    });
}
<commit_msg>Benchmarks for xxHash. Significantly faster for larger input<commit_after>#![feature(test)]

extern crate multibloom;
extern crate test;
extern crate rand;
extern crate twox_hash;

use test::{Bencher, black_box};
use multibloom::BloomFilter;
use rand::Rng;
use twox_hash::RandomXxHashBuilder;

#[bench]
fn bench_add_1_sip(b: &mut Bencher) {
    let mut bloom = BloomFilter::new(1000, 10);
    let bytes = rand::thread_rng().gen_iter::<u8>().take(1).collect::<Vec<u8>>();
    b.iter(|| {
        bloom.add(&bytes);
        black_box(&bloom);
    });
}

#[bench]
fn bench_add_64_sip(b: &mut Bencher) {
    let mut bloom = BloomFilter::new(1000, 10);
    let bytes = rand::thread_rng().gen_iter::<u8>().take(64).collect::<Vec<u8>>();

    b.iter(|| {
        bloom.add(&bytes);
        black_box(&bloom);
    });
}

#[bench]
fn bench_add_1k_sip(b: &mut Bencher) {
    let mut bloom = BloomFilter::new(1000, 10);
    let bytes = rand::thread_rng().gen_iter::<u8>().take(1024).collect::<Vec<u8>>();
    b.iter(|| {
        bloom.add(&bytes);
        black_box(&bloom);
    });
}

#[bench]
fn bench_add_1_xx_hash(b: &mut Bencher) {
    let mut bloom = BloomFilter::new_with_hasher(RandomXxHashBuilder::default(), 1000, 10);
    let bytes = rand::thread_rng().gen_iter::<u8>().take(1).collect::<Vec<u8>>();
    b.iter(|| {
        bloom.add(&bytes);
        black_box(&bloom);
    });
}

#[bench]
fn bench_add_64_xx_hash(b: &mut Bencher) {
    let mut bloom = BloomFilter::new_with_hasher(RandomXxHashBuilder::default(), 1000, 10);
    let bytes = rand::thread_rng().gen_iter::<u8>().take(64).collect::<Vec<u8>>();

    b.iter(|| {
        bloom.add(&bytes);
        black_box(&bloom);
    });
}

#[bench]
fn bench_add_1k_xx_hash(b: &mut Bencher) {
    let mut bloom = BloomFilter::new_with_hasher(RandomXxHashBuilder::default(), 1000, 10);
    let bytes = rand::thread_rng().gen_iter::<u8>().take(1024).collect::<Vec<u8>>();
    b.iter(|| {
        bloom.add(&bytes);
        black_box(&bloom);
    });
}

<|endoftext|>


<commit_before>//! Array Virtual Table
//! Port of [carray](http://www.sqlite.org/cgi/src/finfo?name=ext/misc/carray.c) C extension.
use std::default::Default;
use std::os::raw::{c_char, c_int, c_void};
use std::rc::Rc;

use ffi;
use types::{ToSql, ToSqlOutput, Value};
use vtab::{self, declare_vtab, Context, IndexInfo, VTab, VTabCursor, Values};
use {Connection, Error, Result};

// http://sqlite.org/bindptr.html

pub(crate) const ARRAY_TYPE: *const c_char = b"rarray\0" as *const u8 as *const c_char;

pub(crate) unsafe extern "C" fn free_array(p: *mut c_void) {
    let _: Array = Rc::from_raw(p as *const Vec<Value>);
}

pub type Array = Rc<Vec<Value>>;

impl ToSql for Array {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::Array(self.clone()))
    }
}

/// Register the "rarray" module.
pub fn load_module(conn: &Connection) -> Result<()> {
    let aux: Option<()> = None;
    conn.create_module("rarray", &ARRAY_MODULE, aux)
}

eponymous_module!(
    ARRAY_MODULE,
    ArrayTab,
    (),
    ArrayTabCursor,
    None,
    array_connect,
    array_best_index,
    array_disconnect,
    None,
    array_open,
    array_close,
    array_filter,
    array_next,
    array_eof,
    array_column,
    array_rowid
);

// Column numbers
// const CARRAY_COLUMN_VALUE : c_int = 0;
const CARRAY_COLUMN_POINTER: c_int = 1;

/// An instance of the Array virtual table
#[repr(C)]
struct ArrayTab {
    /// Base class. Must be first
    base: ffi::sqlite3_vtab,
}

impl VTab for ArrayTab {
    type Aux = ();
    type Cursor = ArrayTabCursor;

    unsafe fn connect(db: *mut ffi::sqlite3, _aux: *mut (), _args: &[&[u8]]) -> Result<ArrayTab> {
        let vtab = ArrayTab {
            base: Default::default(),
        };
        try!(declare_vtab(db, "CREATE TABLE x(value,pointer hidden)"));
        Ok(vtab)
    }

    fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
        // Index of the pointer= constraint
        let mut ptr_idx = None;
        for (i, constraint) in info.constraints().enumerate() {
            if !constraint.is_usable() {
                continue;
            }
            if constraint.operator() != vtab::IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_EQ {
                continue;
            }
            match constraint.column() {
                CARRAY_COLUMN_POINTER => {
                    ptr_idx = Some(i);
                }
                _ => {}
            }
        }
        if let Some(ptr_idx) = ptr_idx {
            {
                let mut constraint_usage = info.constraint_usage(ptr_idx);
                constraint_usage.set_argv_index(1);
                constraint_usage.set_omit(true);
            }
            info.set_estimated_cost(1f64);
            info.set_estimated_rows(100);
            info.set_idx_num(1);
        } else {
            info.set_estimated_cost(2_147_483_647f64);
            info.set_estimated_rows(2_147_483_647);
            info.set_idx_num(0);
        }
        Ok(())
    }

    fn open(&self) -> Result<ArrayTabCursor> {
        Ok(ArrayTabCursor::new())
    }
}

/// A cursor for the Array virtual table
#[repr(C)]
struct ArrayTabCursor {
    /// Base class. Must be first
    base: ffi::sqlite3_vtab_cursor,
    /// The rowid
    row_id: i64,
    /// Pointer to the array of values ("pointer")
    ptr: Option<Array>,
}

impl ArrayTabCursor {
    fn new() -> ArrayTabCursor {
        ArrayTabCursor {
            base: Default::default(),
            row_id: 0,
            ptr: None,
        }
    }
    fn len(&self) -> i64 {
        match self.ptr {
            Some(ref a) => a.len() as i64,
            _ => 0,
        }
    }
}
impl VTabCursor for ArrayTabCursor {
    type Table = ArrayTab;

    fn vtab(&self) -> &ArrayTab {
        unsafe { &*(self.base.pVtab as *const ArrayTab) }
    }
    fn filter(&mut self, idx_num: c_int, _idx_str: Option<&str>, args: &Values) -> Result<()> {
        if idx_num > 0 {
            self.ptr = try!(args.get_array(0));
        } else {
            self.ptr = None;
        }
        self.row_id = 1;
        Ok(())
    }
    fn next(&mut self) -> Result<()> {
        self.row_id += 1;
        Ok(())
    }
    fn eof(&self) -> bool {
        self.row_id > self.len()
    }
    fn column(&self, ctx: &mut Context, i: c_int) -> Result<()> {
        match i {
            CARRAY_COLUMN_POINTER => Ok(()),
            _ => {
                if let Some(ref array) = self.ptr {
                    let value = &array[i as usize];
                    ctx.set_result(&value)
                } else {
                    Ok(())
                }
            }
        }
    }
    fn rowid(&self) -> Result<i64> {
        Ok(self.row_id)
    }
}
<commit_msg>Carray module ported to Rust<commit_after>//! Array Virtual Table
//! Port of [carray](http://www.sqlite.org/cgi/src/finfo?name=ext/misc/carray.c) C extension.
use std::default::Default;
use std::os::raw::{c_char, c_int, c_void};
use std::rc::Rc;

use ffi;
use types::{ToSql, ToSqlOutput, Value};
use vtab::{self, declare_vtab, Context, IndexInfo, VTab, VTabCursor, Values};
use {Connection, Error, Result};

// http://sqlite.org/bindptr.html

pub(crate) const ARRAY_TYPE: *const c_char = b"rarray\0" as *const u8 as *const c_char;

pub(crate) unsafe extern "C" fn free_array(p: *mut c_void) {
    let _: Array = Rc::from_raw(p as *const Vec<Value>);
}

pub type Array = Rc<Vec<Value>>;

impl ToSql for Array {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::Array(self.clone()))
    }
}

/// Register the "rarray" module.
pub fn load_module(conn: &Connection) -> Result<()> {
    let aux: Option<()> = None;
    conn.create_module("rarray", &ARRAY_MODULE, aux)
}

eponymous_module!(
    ARRAY_MODULE,
    ArrayTab,
    (),
    ArrayTabCursor,
    None,
    array_connect,
    array_best_index,
    array_disconnect,
    None,
    array_open,
    array_close,
    array_filter,
    array_next,
    array_eof,
    array_column,
    array_rowid
);

// Column numbers
// const CARRAY_COLUMN_VALUE : c_int = 0;
const CARRAY_COLUMN_POINTER: c_int = 1;

/// An instance of the Array virtual table
#[repr(C)]
struct ArrayTab {
    /// Base class. Must be first
    base: ffi::sqlite3_vtab,
}

impl VTab for ArrayTab {
    type Aux = ();
    type Cursor = ArrayTabCursor;

    unsafe fn connect(db: *mut ffi::sqlite3, _aux: *mut (), _args: &[&[u8]]) -> Result<ArrayTab> {
        let vtab = ArrayTab {
            base: Default::default(),
        };
        try!(declare_vtab(db, "CREATE TABLE x(value,pointer hidden)"));
        Ok(vtab)
    }

    fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
        // Index of the pointer= constraint
        let mut ptr_idx = None;
        for (i, constraint) in info.constraints().enumerate() {
            if !constraint.is_usable() {
                continue;
            }
            if constraint.operator() != vtab::IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_EQ {
                continue;
            }
            match constraint.column() {
                CARRAY_COLUMN_POINTER => {
                    ptr_idx = Some(i);
                }
                _ => {}
            }
        }
        if let Some(ptr_idx) = ptr_idx {
            {
                let mut constraint_usage = info.constraint_usage(ptr_idx);
                constraint_usage.set_argv_index(1);
                constraint_usage.set_omit(true);
            }
            info.set_estimated_cost(1f64);
            info.set_estimated_rows(100);
            info.set_idx_num(1);
        } else {
            info.set_estimated_cost(2_147_483_647f64);
            info.set_estimated_rows(2_147_483_647);
            info.set_idx_num(0);
        }
        Ok(())
    }

    fn open(&self) -> Result<ArrayTabCursor> {
        Ok(ArrayTabCursor::new())
    }
}

/// A cursor for the Array virtual table
#[repr(C)]
struct ArrayTabCursor {
    /// Base class. Must be first
    base: ffi::sqlite3_vtab_cursor,
    /// The rowid
    row_id: i64,
    /// Pointer to the array of values ("pointer")
    ptr: Option<Array>,
}

impl ArrayTabCursor {
    fn new() -> ArrayTabCursor {
        ArrayTabCursor {
            base: Default::default(),
            row_id: 0,
            ptr: None,
        }
    }
    fn len(&self) -> i64 {
        match self.ptr {
            Some(ref a) => a.len() as i64,
            _ => 0,
        }
    }
}
impl VTabCursor for ArrayTabCursor {
    type Table = ArrayTab;

    fn vtab(&self) -> &ArrayTab {
        unsafe { &*(self.base.pVtab as *const ArrayTab) }
    }
    fn filter(&mut self, idx_num: c_int, _idx_str: Option<&str>, args: &Values) -> Result<()> {
        if idx_num > 0 {
            self.ptr = try!(args.get_array(0));
        } else {
            self.ptr = None;
        }
        self.row_id = 1;
        Ok(())
    }
    fn next(&mut self) -> Result<()> {
        self.row_id += 1;
        Ok(())
    }
    fn eof(&self) -> bool {
        self.row_id > self.len()
    }
    fn column(&self, ctx: &mut Context, i: c_int) -> Result<()> {
        match i {
            CARRAY_COLUMN_POINTER => Ok(()),
            _ => {
                if let Some(ref array) = self.ptr {
                    let value = &array[(self.row_id - 1) as usize];
                    ctx.set_result(&value)
                } else {
                    Ok(())
                }
            }
        }
    }
    fn rowid(&self) -> Result<i64> {
        Ok(self.row_id)
    }
}

#[cfg(test)]
mod test {
    use std::rc::Rc;
    use types::Value;
    use vtab::array;
    use Connection;

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_array_module() {
        let db = Connection::open_in_memory().unwrap();
        array::load_module(&db).unwrap();

        let v = vec![1i64, 2, 3, 4];
        let values = v.into_iter().map(|i| Value::from(i)).collect();
        let ptr = Rc::new(values);
        let mut stmt = db.prepare("SELECT value from rarray(?);").unwrap();

        let rows = stmt.query_map(&[&ptr], |row| row.get::<_, i64>(0)).unwrap();
        let mut count = 0;
        for (i, value) in rows.enumerate() {
            assert_eq!(i as i64, value.unwrap()-1);
            count += 1;
        }
        assert_eq!(4, count);
    }
}
<|endoftext|>