<commit_before>use rand::{seq, Rng, SeedableRng, XorShiftRng};
use std::hash::Hash;
use vec_map::VecMap;
use Deciban;

/// Seed a RNG from any hashable value.
pub fn seeded_rng(seed: &impl Hash) -> XorShiftRng {
    use std::collections::hash_map::DefaultHasher;
    use std::hash::Hasher;

    let mut hasher = DefaultHasher::new();
    seed.hash(&mut hasher);
    let hash = hasher.finish().to_be();
    // XorShift seed mustn't be all-0.
    let hash = if hash == 0 { 1 } else { hash };

    let seed = unsafe { ::std::mem::transmute::<[u64; 2], [u8; 16]>([hash, hash]) };
    SeedableRng::from_seed(seed)
}

/// Additional methods for random number generators.
pub trait RngExt {
    /// Return true with 50 % probability.
    fn coinflip(&mut self) -> bool;

    /// Return true with probability 1 / n.
    fn one_chance_in(&mut self, n: u32) -> bool;

    /// Return true with p probability.
    fn with_chance(&mut self, p: f32) -> bool;

    /// Return true with the probability corresponding to the log odds with
    /// the given deciban value.
    fn with_log_odds(&mut self, db: Deciban) -> bool;

    /// Pick a single random element from a slice.
    fn pick_slice_ref<'a, U>(&mut self, slice: &'a [U]) -> Option<&'a U>;

    /// Pick a single random element from a slice.
    fn pick_slice<'a, U: Clone>(&mut self, slice: &'a [U]) -> Option<U>;

    /// Pick a single random element from an iterator
    fn pick_iter<U>(&mut self, iter: impl IntoIterator<Item = U>) -> Option<U>;
}

impl<T: Rng> RngExt for T {
    fn coinflip(&mut self) -> bool { self.gen_bool(1.0 / 2.0) }

    fn one_chance_in(&mut self, n: u32) -> bool { self.gen_bool(1.0 / n as f64) }

    fn with_chance(&mut self, p: f32) -> bool { self.gen_range(0.0, 1.0) < p }

    fn with_log_odds(&mut self, db: Deciban) -> bool { db > self.gen::<Deciban>() }

    fn pick_slice_ref<'a, U>(&mut self, slice: &'a [U]) -> Option<&'a U> {
        seq::sample_slice_ref(self, slice, 1).pop()
    }

    fn pick_slice<U: Clone>(&mut self, slice: &[U]) -> Option<U> {
        seq::sample_slice(self, slice, 1).pop()
    }

    /// Pick a single random element from an iterator
    fn pick_iter<U>(&mut self, iter: impl IntoIterator<Item = U>) -> Option<U> {
        seq::sample_iter(self, iter, 1).unwrap_or(Vec::new()).pop()
    }
}

/// Lazily evaluated random permutation.
pub struct RandomPermutation<'a, R: Rng + 'static> {
    remain: usize,
    shuffle: VecMap<usize>,
    rng: &'a mut R,
}

impl<'a, R: Rng + 'static> RandomPermutation<'a, R> {
    pub fn new(rng: &'a mut R, n: usize) -> RandomPermutation<'a, R> {
        RandomPermutation {
            remain: n,
            shuffle: VecMap::new(),
            rng,
        }
    }
}

impl<'a, R: Rng + 'static> Iterator for RandomPermutation<'a, R> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        if self.remain == 0 {
            return None;
        }

        let swap_idx = self.rng.gen_range(0, self.remain);
        self.remain -= 1;

        let head = *self.shuffle.get(self.remain).unwrap_or(&self.remain);
        Some(self.shuffle.insert(swap_idx, head).unwrap_or(swap_idx))
    }
}
<commit_msg>RngExt ?Sized<commit_after>use rand::{seq, Rng, SeedableRng, XorShiftRng};
use std::hash::Hash;
use vec_map::VecMap;
use Deciban;

/// Seed a RNG from any hashable value.
pub fn seeded_rng(seed: &impl Hash) -> XorShiftRng {
    use std::collections::hash_map::DefaultHasher;
    use std::hash::Hasher;

    let mut hasher = DefaultHasher::new();
    seed.hash(&mut hasher);
    let hash = hasher.finish().to_be();
    // XorShift seed mustn't be all-0.
    let hash = if hash == 0 { 1 } else { hash };

    let seed = unsafe { ::std::mem::transmute::<[u64; 2], [u8; 16]>([hash, hash]) };
    SeedableRng::from_seed(seed)
}

/// Additional methods for random number generators.
pub trait RngExt {
    /// Return true with 50 % probability.
    fn coinflip(&mut self) -> bool;

    /// Return true with probability 1 / n.
    fn one_chance_in(&mut self, n: u32) -> bool;

    /// Return true with p probability.
    fn with_chance(&mut self, p: f32) -> bool;

    /// Return true with the probability corresponding to the log odds with
    /// the given deciban value.
    fn with_log_odds(&mut self, db: Deciban) -> bool;

    /// Pick a single random element from a slice.
    fn pick_slice_ref<'a, U>(&mut self, slice: &'a [U]) -> Option<&'a U>;

    /// Pick a single random element from a slice.
    fn pick_slice<'a, U: Clone>(&mut self, slice: &'a [U]) -> Option<U>;

    /// Pick a single random element from an iterator
    fn pick_iter<U>(&mut self, iter: impl IntoIterator<Item = U>) -> Option<U>;
}

impl<T: Rng + ?Sized> RngExt for T {
    fn coinflip(&mut self) -> bool { self.gen_bool(1.0 / 2.0) }

    fn one_chance_in(&mut self, n: u32) -> bool { self.gen_bool(1.0 / n as f64) }

    fn with_chance(&mut self, p: f32) -> bool { self.gen_range(0.0, 1.0) < p }

    fn with_log_odds(&mut self, db: Deciban) -> bool { db > self.gen::<Deciban>() }

    fn pick_slice_ref<'a, U>(&mut self, slice: &'a [U]) -> Option<&'a U> {
        seq::sample_slice_ref(self, slice, 1).pop()
    }

    fn pick_slice<U: Clone>(&mut self, slice: &[U]) -> Option<U> {
        seq::sample_slice(self, slice, 1).pop()
    }

    /// Pick a single random element from an iterator
    fn pick_iter<U>(&mut self, iter: impl IntoIterator<Item = U>) -> Option<U> {
        seq::sample_iter(self, iter, 1).unwrap_or(Vec::new()).pop()
    }
}

/// Lazily evaluated random permutation.
pub struct RandomPermutation<'a, R: Rng + 'static> {
    remain: usize,
    shuffle: VecMap<usize>,
    rng: &'a mut R,
}

impl<'a, R: Rng + 'static> RandomPermutation<'a, R> {
    pub fn new(rng: &'a mut R, n: usize) -> RandomPermutation<'a, R> {
        RandomPermutation {
            remain: n,
            shuffle: VecMap::new(),
            rng,
        }
    }
}

impl<'a, R: Rng + 'static> Iterator for RandomPermutation<'a, R> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        if self.remain == 0 {
            return None;
        }

        let swap_idx = self.rng.gen_range(0, self.remain);
        self.remain -= 1;

        let head = *self.shuffle.get(self.remain).unwrap_or(&self.remain);
        Some(self.shuffle.insert(swap_idx, head).unwrap_or(swap_idx))
    }
}
<|endoftext|>


<commit_before>use std::mem;

const PCG32_DEFAULT_STATE: u64 = 0x853c49e6748fea9b;
const PCG32_DEFAULT_STREAM: u64 = 0xda3e39cb94b95bdb;
const PCG32_MULT: u64 = 0x5851f42d4c957f2d;

pub struct RNG {
    state: u64,
    inc: u64,
}

impl RNG {
    pub fn new() -> RNG {
        RNG {
            state: PCG32_DEFAULT_STATE,
            inc: PCG32_DEFAULT_STREAM,
        }
    }

    pub fn uniform_u32(&mut self) -> u32 {
        let oldstate = self.state;
        self.state = oldstate * PCG32_MULT + self.inc;
        let xorshifted = (((oldstate >> 18) ^ oldstate) >> 27) as u32;
        let rot = (oldstate >> 59) as u32;

        (xorshifted >> rot) | (xorshifted << ((!rot + 1) & 31))
    }

    pub fn uniform_u32_bounded(&mut self, b: u32) -> u32 {
        let threshold = (!b + 1) & b;
        loop {
            let r = self.uniform_u32();
            if r >= threshold {
                return r % b;
            }
        }
    }

    pub fn uniform_f32(&mut self) -> f32 {
        const UPPER_MASK: u32 = 0x3F800000;
        const LOWER_MASK: u32 = 0x7FFFFF;
        let tmp = UPPER_MASK | (self.uniform_u32() & LOWER_MASK);
        let result: f32 = unsafe { mem::transmute(tmp) };
        result - 1.0
    }

    pub fn set_sequence(&mut self, seed: u64) {
        self.state = 0;
        self.inc = (seed << 1) | 1;
        let _ = self.uniform_u32();
        self.state += PCG32_DEFAULT_STATE;
        let _ = self.uniform_u32();
    }
}
<commit_msg>Use same impl for RNG::uniform_f32() as PBRT<commit_after>use std::mem;

use ::ONE_MINUS_EPSILON;

const PCG32_DEFAULT_STATE: u64 = 0x853c49e6748fea9b;
const PCG32_DEFAULT_STREAM: u64 = 0xda3e39cb94b95bdb;
const PCG32_MULT: u64 = 0x5851f42d4c957f2d;

pub struct RNG {
    state: u64,
    inc: u64,
}

impl RNG {
    pub fn new() -> RNG {
        RNG {
            state: PCG32_DEFAULT_STATE,
            inc: PCG32_DEFAULT_STREAM,
        }
    }

    pub fn uniform_u32(&mut self) -> u32 {
        let oldstate = self.state;
        self.state = oldstate * PCG32_MULT + self.inc;
        let xorshifted = (((oldstate >> 18) ^ oldstate) >> 27) as u32;
        let rot = (oldstate >> 59) as u32;

        (xorshifted >> rot) | (xorshifted << ((!rot + 1) & 31))
    }

    pub fn uniform_u32_bounded(&mut self, b: u32) -> u32 {
        let threshold = (!b + 1) & b;
        loop {
            let r = self.uniform_u32();
            if r >= threshold {
                return r % b;
            }
        }
    }

    pub fn uniform_f32(&mut self) -> f32 {
        (self.uniform_u32() as f32 * 2.3283064365386963e-10).min(ONE_MINUS_EPSILON)

    }

    pub fn set_sequence(&mut self, seed: u64) {
        self.state = 0;
        self.inc = (seed << 1) | 1;
        let _ = self.uniform_u32();
        self.state += PCG32_DEFAULT_STATE;
        let _ = self.uniform_u32();
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::{File, OpenOptions};
use std::old_io::{Open, ReadWrite, Command};
use std::old_io::process::StdioContainer;
use std::os::unix::AsRawFd;
use libc::{c_ushort, c_int, c_ulong};
use std::str;

pub struct TTY {
    file: File,
    dimensions: (usize, usize),
    original_state: String
}

pub trait IO {
    fn write(&mut self, line: &str);
    fn read(&mut self) -> Option<String>;
    fn last(&self) -> &str;
    fn lines(&self) -> Vec<String>;
    fn dimensions(&self) -> (usize, usize);
    fn reset(&self);
}

impl IO for TTY {
    fn write(&mut self, line: &str) {
        let it = format!("{}", line);
        self.file.write(it.as_bytes()).unwrap();
    }

    fn read(&mut self) -> Option<String> {
        let mut buffer = [0] ;
        let res = match self.file.read(&mut buffer) {
            Ok(c) if  c > 0 => {
                str::from_utf8(&buffer).ok().map(|x| x.to_string())
            },
            _ => None,
        };
        res
    }

    fn last(&self) -> &str {
        "fail"
    }

    fn lines(&self) -> Vec<String> {
        let mut lines: Vec<String> = Vec::new();
        lines.push("fail".to_string());
        lines
    }

    fn dimensions(&self) -> (usize, usize) {
        self.dimensions
    }

    fn reset(&self) {
        TTY::stty(&self.file, &[self.original_state.as_slice()]);
    }
}

impl TTY {
    pub fn new() -> TTY {
        let path = Path::new("/dev/tty");
        let file = OpenOptions::new().read(true).write(true).open(&path).unwrap();
        let dimension = TTY::get_window_size(&file);
        let orig_state = TTY::previous_state(&file);

        TTY::no_echo_no_escaping(&file);

        TTY {
            original_state: orig_state,
            dimensions: dimension,
            file: file,
        }
    }

    fn get_window_size(path: &File) -> (usize, usize) {
        extern {
            fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
        }
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const TIOCGWINSZ: c_ulong = 0x40087468;

        #[cfg(any(target_os = "linux", target_os = "android"))]
        const TIOCGWINSZ: c_ulong = 0x00005413;

        #[repr(C)]
        struct TermSize {
            rows: c_ushort,
            cols: c_ushort,
            x: c_ushort,
            y: c_ushort,
        }

        let size = TermSize { rows: 0, cols: 0, x: 0, y: 0 };
        if unsafe { ioctl(path.as_raw_fd(), TIOCGWINSZ, &size) } == 0 {
            (size.cols as usize, size.rows as usize)
        } else {
            panic!("Could not read winsize from /dev/tty")
        }
    }

    fn stty(file: &File, args: &[&str]) -> Option<String> {
        let container = StdioContainer::InheritFd(file.as_raw_fd());
        let output = Command::new("stty").args(args).stdin(container).output().unwrap();
        String::from_utf8(output.output).ok()
    }

    fn no_echo_no_escaping(file: &File) {
        TTY::stty(file, &["-echo", "-icanon"]);
    }

    fn previous_state(file: &File) -> String {
        TTY::stty(file, &["-g"]).unwrap_or("".to_string())
    }
}
<commit_msg>Use new process::Comand<commit_after>use std::io::prelude::*;
use std::fs::{File, OpenOptions};
use std::process::{Command, Stdio};
use std::os::unix::AsRawFd;
use libc::{c_ushort, c_int, c_ulong};
use std::str;

pub struct TTY {
    file: File,
    dimensions: (usize, usize),
    original_state: String
}

pub trait IO {
    fn write(&mut self, line: &str);
    fn read(&mut self) -> Option<String>;
    fn last(&self) -> &str;
    fn lines(&self) -> Vec<String>;
    fn dimensions(&self) -> (usize, usize);
    fn reset(&self);
}

impl IO for TTY {
    fn write(&mut self, line: &str) {
        let it = format!("{}", line);
        self.file.write(it.as_bytes()).unwrap();
    }

    fn read(&mut self) -> Option<String> {
        let mut buffer = [0] ;
        let res = match self.file.read(&mut buffer) {
            Ok(c) if  c > 0 => {
                str::from_utf8(&buffer).ok().map(|x| x.to_string())
            },
            _ => None,
        };
        res
    }

    fn last(&self) -> &str {
        "fail"
    }

    fn lines(&self) -> Vec<String> {
        let mut lines: Vec<String> = Vec::new();
        lines.push("fail".to_string());
        lines
    }

    fn dimensions(&self) -> (usize, usize) {
        self.dimensions
    }

    fn reset(&self) {
        TTY::stty(&self.file, &[self.original_state.as_slice()]);
    }
}

impl TTY {
    pub fn new() -> TTY {
        let path = Path::new("/dev/tty");
        let file = OpenOptions::new().read(true).write(true).open(&path).unwrap();
        let dimension = TTY::get_window_size(&file);
        let orig_state = TTY::previous_state(&file);

        TTY::no_echo_no_escaping(&file);

        TTY {
            original_state: orig_state,
            dimensions: dimension,
            file: file,
        }
    }

    fn get_window_size(path: &File) -> (usize, usize) {
        extern {
            fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
        }
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const TIOCGWINSZ: c_ulong = 0x40087468;

        #[cfg(any(target_os = "linux", target_os = "android"))]
        const TIOCGWINSZ: c_ulong = 0x00005413;

        #[repr(C)]
        struct TermSize {
            rows: c_ushort,
            cols: c_ushort,
            x: c_ushort,
            y: c_ushort,
        }

        let size = TermSize { rows: 0, cols: 0, x: 0, y: 0 };
        if unsafe { ioctl(path.as_raw_fd(), TIOCGWINSZ, &size) } == 0 {
            (size.cols as usize, size.rows as usize)
        } else {
            panic!("Could not read winsize from /dev/tty")
        }
    }

    fn stty(file: &File, args: &[&str]) -> Option<String> {
        let output = Command::new("stty").args(args).stdin(Stdio::capture()).output().unwrap();
        String::from_utf8(output.stdout).ok()
    }

    fn no_echo_no_escaping(file: &File) {
        TTY::stty(file, &["-echo", "-icanon"]);
    }

    fn previous_state(file: &File) -> String {
        TTY::stty(file, &["-g"]).unwrap_or("".to_string())
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins) within
//! a Cargo build. You still need the `capnp` binary (implemented in C++).
//! (If you use a package manager, try looking for a package called
//! `capnproto`.)
//!
//! In your Cargo.toml:
//!
//! ```ignore
//! [package]
//! build = "build.rs"
//!
//! [build-dependencies]
//! capnpc = "0.9"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     capnpc::CompilerCommand::new()
//!         .src_prefix("schema")
//!         .file("schema/foo.capnp")
//!         .file("schema/bar.capnp")
//!         .run().expect("schema compiler command");
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
mod pointer_constants;
pub mod schema;

use std::path::{Path, PathBuf};

#[derive(Copy, Clone)]
pub enum RustEdition {
    Rust2015,
    Rust2018
}

fn run_command(mut command: ::std::process::Command, edition: RustEdition) -> ::capnp::Result<()> {
    let mut p = command.spawn()?;
    ::codegen::generate_code(p.stdout.take().unwrap(),
                         ::std::path::Path::new(&::std::env::var("OUT_DIR").unwrap()), edition)?;
    let exit_status = p.wait()?;
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!("Non-success exit status: {}", exit_status)))
    } else {
        Ok(())
    }
}

/// A builder object for schema compiler commands.
pub struct CompilerCommand {
    files: Vec<PathBuf>,
    src_prefixes: Vec<PathBuf>,
    import_paths: Vec<PathBuf>,
    no_standard_import: bool,
    rust_edition: RustEdition,
}

impl CompilerCommand {
    /// Creates a new, empty command.
    pub fn new() -> CompilerCommand {
        CompilerCommand {
            files: Vec::new(),
            src_prefixes: Vec::new(),
            import_paths: Vec::new(),
            no_standard_import: false,
            rust_edition: RustEdition::Rust2015,
        }
    }

    /// Adds a file to be compiled.
    pub fn file<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.files.push(path.as_ref().to_path_buf());
        self
    }

    /// Adds a --src-prefix flag. For all files specified for compilation that start
    /// with `prefix`, removes the prefix when computing output filenames.
    pub fn src_prefix<'a, P>(&'a mut self, prefix: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.src_prefixes.push(prefix.as_ref().to_path_buf());
        self
    }

    /// Adds an --import_path flag. Adds `dir` to the list of directories searched
    /// for absolute imports.
    pub fn import_path<'a, P>(&'a mut self, dir: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.import_paths.push(dir.as_ref().to_path_buf());
        self
    }

    /// Adds the --no-standard-import flag, indicating that the default import paths of
    /// /usr/include and /usr/local/include should not bet included.
    pub fn no_standard_import<'a>(&'a mut self) -> &'a mut CompilerCommand {
        self.no_standard_import = true;
        self
    }

    /// Sets the Rust edition of the generated code.
    pub fn edition(&mut self, rust_edition: RustEdition) -> &mut Self {
        self.rust_edition = rust_edition;
        self
    }

    /// Runs the command.
    pub fn run(&mut self) -> ::capnp::Result<()> {
        let mut command = ::std::process::Command::new("capnp");
        command.arg("compile").arg("-o").arg("-");

        if self.no_standard_import {
            command.arg("--no-standard-import");
        }

        for import_path in &self.import_paths {
            command.arg(&format!("--import-path={}", import_path.display()));
        }

        for src_prefix in &self.src_prefixes {
            command.arg(&format!("--src-prefix={}", src_prefix.display()));
        }

        for file in &self.files {
            command.arg(&format!("{}", file.display()));
        }

        command.stdout(::std::process::Stdio::piped());
        command.stderr(::std::process::Stdio::inherit());

        run_command(command, self.rust_edition).map_err(|error| {
            ::capnp::Error::failed(format!(
                "Error while trying to execute `capnp compile`: {}.  \
                 Please verify that version 0.5.2 or higher of the capnp executable \
                 is installed on your system. See https://capnproto.org/install.html",
                error))})
    }
}
<commit_msg>Added output path option for build scripts<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins) within
//! a Cargo build. You still need the `capnp` binary (implemented in C++).
//! (If you use a package manager, try looking for a package called
//! `capnproto`.)
//!
//! In your Cargo.toml:
//!
//! ```ignore
//! [package]
//! build = "build.rs"
//!
//! [build-dependencies]
//! capnpc = "0.9"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     capnpc::CompilerCommand::new()
//!         .src_prefix("schema")
//!         .file("schema/foo.capnp")
//!         .file("schema/bar.capnp")
//!         .run().expect("schema compiler command");
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
mod pointer_constants;
pub mod schema;

use std::path::{Path, PathBuf};

#[derive(Copy, Clone)]
pub enum RustEdition {
    Rust2015,
    Rust2018,
}

fn run_command(
    mut command: ::std::process::Command,
    edition: RustEdition,
    path: &PathBuf,
) -> ::capnp::Result<()> {
    let mut p = command.spawn()?;
    ::codegen::generate_code(p.stdout.take().unwrap(), path.as_path(), edition)?;
    let exit_status = p.wait()?;
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!(
            "Non-success exit status: {}",
            exit_status
        )))
    } else {
        Ok(())
    }
}

/// A builder object for schema compiler commands.
pub struct CompilerCommand {
    files: Vec<PathBuf>,
    src_prefixes: Vec<PathBuf>,
    import_paths: Vec<PathBuf>,
    no_standard_import: bool,
    output_path: PathBuf,
    rust_edition: RustEdition,
}

impl CompilerCommand {
    /// Creates a new, empty command.
    pub fn new() -> CompilerCommand {
        CompilerCommand {
            files: Vec::new(),
            src_prefixes: Vec::new(),
            import_paths: Vec::new(),
            no_standard_import: false,
            output_path: PathBuf::from(&::std::env::var("OUT_DIR").unwrap()),
            rust_edition: RustEdition::Rust2015,
        }
    }

    /// Adds a file to be compiled.
    pub fn file<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.files.push(path.as_ref().to_path_buf());
        self
    }

    /// Adds a --src-prefix flag. For all files specified for compilation that start
    /// with `prefix`, removes the prefix when computing output filenames.
    pub fn src_prefix<'a, P>(&'a mut self, prefix: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.src_prefixes.push(prefix.as_ref().to_path_buf());
        self
    }

    /// Adds an --import_path flag. Adds `dir` to the list of directories searched
    /// for absolute imports.
    pub fn import_path<'a, P>(&'a mut self, dir: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.import_paths.push(dir.as_ref().to_path_buf());
        self
    }

    /// Adds the --no-standard-import flag, indicating that the default import paths of
    /// /usr/include and /usr/local/include should not bet included.
    pub fn no_standard_import<'a>(&'a mut self) -> &'a mut CompilerCommand {
        self.no_standard_import = true;
        self
    }

    /// Sets the Rust edition of the generated code.
    pub fn edition(&mut self, rust_edition: RustEdition) -> &mut Self {
        self.rust_edition = rust_edition;
        self
    }

    ///Sets the output directory of generated code. Default is OUT_DIR
    pub fn output_path<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.output_path = path.as_ref().to_path_buf();
        self
    }

    /// Runs the command.
    pub fn run(&mut self) -> ::capnp::Result<()> {
        let mut command = ::std::process::Command::new("capnp");
        command.arg("compile").arg("-o").arg("-");

        if self.no_standard_import {
            command.arg("--no-standard-import");
        }

        for import_path in &self.import_paths {
            command.arg(&format!("--import-path={}", import_path.display()));
        }

        for src_prefix in &self.src_prefixes {
            command.arg(&format!("--src-prefix={}", src_prefix.display()));
        }

        for file in &self.files {
            command.arg(&format!("{}", file.display()));
        }

        command.stdout(::std::process::Stdio::piped());
        command.stderr(::std::process::Stdio::inherit());

        run_command(command, self.rust_edition, &self.output_path).map_err(|error| {
            ::capnp::Error::failed(format!(
                "Error while trying to execute `capnp compile`: {}.  \
                 Please verify that version 0.5.2 or higher of the capnp executable \
                 is installed on your system. See https://capnproto.org/install.html",
                error
            ))
        })
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins) within
//! a Cargo build. You still need the `capnp` binary (implemented in C++).
//! (If you use a package manager, try looking for a package called
//! `capnproto`.)
//!
//! In your Cargo.toml:
//!
//! ```ignore
//! [package]
//! build = "build.rs"
//!
//! [build-dependencies]
//! capnpc = "0.9"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     capnpc::CompilerCommand::new()
//!         .src_prefix("schema")
//!         .file("schema/foo.capnp")
//!         .file("schema/bar.capnp")
//!         .run().expect("schema compiler command");
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
mod pointer_constants;
pub mod schema;

use std::path::{Path, PathBuf};

#[derive(Copy, Clone)]
pub enum RustEdition {
    Rust2015,
    Rust2018
}

fn run_command(mut command: ::std::process::Command, edition: RustEdition) -> ::capnp::Result<()> {
    let mut p = command.spawn()?;
    ::codegen::generate_code(p.stdout.take().unwrap(),
                         ::std::path::Path::new(&::std::env::var("OUT_DIR").unwrap()), edition)?;
    let exit_status = p.wait()?;
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!("Non-success exit status: {}", exit_status)))
    } else {
        Ok(())
    }
}

/// A builder object for schema compiler commands.
pub struct CompilerCommand {
    files: Vec<PathBuf>,
    src_prefixes: Vec<PathBuf>,
    import_paths: Vec<PathBuf>,
    no_standard_import: bool,
    rust_edition: RustEdition,
}

impl CompilerCommand {
    /// Creates a new, empty command.
    pub fn new() -> CompilerCommand {
        CompilerCommand {
            files: Vec::new(),
            src_prefixes: Vec::new(),
            import_paths: Vec::new(),
            no_standard_import: false,
            rust_edition: RustEdition::Rust2015,
        }
    }

    /// Adds a file to be compiled.
    pub fn file<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.files.push(path.as_ref().to_path_buf());
        self
    }

    /// Adds a --src-prefix flag. For all files specified for compilation that start
    /// with `prefix`, removes the prefix when computing output filenames.
    pub fn src_prefix<'a, P>(&'a mut self, prefix: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.src_prefixes.push(prefix.as_ref().to_path_buf());
        self
    }

    /// Adds an --import_path flag. Adds `dir` to the list of directories searched
    /// for absolute imports.
    pub fn import_path<'a, P>(&'a mut self, dir: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.import_paths.push(dir.as_ref().to_path_buf());
        self
    }

    /// Adds the --no-standard-import flag, indicating that the default import paths of
    /// /usr/include and /usr/local/include should not bet included.
    pub fn no_standard_import<'a>(&'a mut self) -> &'a mut CompilerCommand {
        self.no_standard_import = true;
        self
    }

    pub fn edition(&mut self, rust_edition: RustEdition) -> &mut Self {
        self.rust_edition = rust_edition;
        self
    }

    /// Runs the command.
    pub fn run(&mut self) -> ::capnp::Result<()> {
        let mut command = ::std::process::Command::new("capnp");
        command.arg("compile").arg("-o").arg("-");

        if self.no_standard_import {
            command.arg("--no-standard-import");
        }

        for import_path in &self.import_paths {
            command.arg(&format!("--import-path={}", import_path.display()));
        }

        for src_prefix in &self.src_prefixes {
            command.arg(&format!("--src-prefix={}", src_prefix.display()));
        }

        for file in &self.files {
            command.arg(&format!("{}", file.display()));
        }

        command.stdout(::std::process::Stdio::piped());
        command.stderr(::std::process::Stdio::inherit());

        run_command(command, self.rust_edition).map_err(|error| {
            ::capnp::Error::failed(format!(
                "Error while trying to execute `capnp compile`: {}.  \
                 Please verify that version 0.5.2 or higher of the capnp executable \
                 is installed on your system. See https://capnproto.org/install.html",
                error))})
    }
}
<commit_msg>add a doc comment<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins) within
//! a Cargo build. You still need the `capnp` binary (implemented in C++).
//! (If you use a package manager, try looking for a package called
//! `capnproto`.)
//!
//! In your Cargo.toml:
//!
//! ```ignore
//! [package]
//! build = "build.rs"
//!
//! [build-dependencies]
//! capnpc = "0.9"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     capnpc::CompilerCommand::new()
//!         .src_prefix("schema")
//!         .file("schema/foo.capnp")
//!         .file("schema/bar.capnp")
//!         .run().expect("schema compiler command");
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
mod pointer_constants;
pub mod schema;

use std::path::{Path, PathBuf};

#[derive(Copy, Clone)]
pub enum RustEdition {
    Rust2015,
    Rust2018
}

fn run_command(mut command: ::std::process::Command, edition: RustEdition) -> ::capnp::Result<()> {
    let mut p = command.spawn()?;
    ::codegen::generate_code(p.stdout.take().unwrap(),
                         ::std::path::Path::new(&::std::env::var("OUT_DIR").unwrap()), edition)?;
    let exit_status = p.wait()?;
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!("Non-success exit status: {}", exit_status)))
    } else {
        Ok(())
    }
}

/// A builder object for schema compiler commands.
pub struct CompilerCommand {
    files: Vec<PathBuf>,
    src_prefixes: Vec<PathBuf>,
    import_paths: Vec<PathBuf>,
    no_standard_import: bool,
    rust_edition: RustEdition,
}

impl CompilerCommand {
    /// Creates a new, empty command.
    pub fn new() -> CompilerCommand {
        CompilerCommand {
            files: Vec::new(),
            src_prefixes: Vec::new(),
            import_paths: Vec::new(),
            no_standard_import: false,
            rust_edition: RustEdition::Rust2015,
        }
    }

    /// Adds a file to be compiled.
    pub fn file<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.files.push(path.as_ref().to_path_buf());
        self
    }

    /// Adds a --src-prefix flag. For all files specified for compilation that start
    /// with `prefix`, removes the prefix when computing output filenames.
    pub fn src_prefix<'a, P>(&'a mut self, prefix: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.src_prefixes.push(prefix.as_ref().to_path_buf());
        self
    }

    /// Adds an --import_path flag. Adds `dir` to the list of directories searched
    /// for absolute imports.
    pub fn import_path<'a, P>(&'a mut self, dir: P) -> &'a mut CompilerCommand
        where P: AsRef<Path>,
    {
        self.import_paths.push(dir.as_ref().to_path_buf());
        self
    }

    /// Adds the --no-standard-import flag, indicating that the default import paths of
    /// /usr/include and /usr/local/include should not bet included.
    pub fn no_standard_import<'a>(&'a mut self) -> &'a mut CompilerCommand {
        self.no_standard_import = true;
        self
    }

    /// Sets the Rust edition of the generated code.
    pub fn edition(&mut self, rust_edition: RustEdition) -> &mut Self {
        self.rust_edition = rust_edition;
        self
    }

    /// Runs the command.
    pub fn run(&mut self) -> ::capnp::Result<()> {
        let mut command = ::std::process::Command::new("capnp");
        command.arg("compile").arg("-o").arg("-");

        if self.no_standard_import {
            command.arg("--no-standard-import");
        }

        for import_path in &self.import_paths {
            command.arg(&format!("--import-path={}", import_path.display()));
        }

        for src_prefix in &self.src_prefixes {
            command.arg(&format!("--src-prefix={}", src_prefix.display()));
        }

        for file in &self.files {
            command.arg(&format!("{}", file.display()));
        }

        command.stdout(::std::process::Stdio::piped());
        command.stderr(::std::process::Stdio::inherit());

        run_command(command, self.rust_edition).map_err(|error| {
            ::capnp::Error::failed(format!(
                "Error while trying to execute `capnp compile`: {}.  \
                 Please verify that version 0.5.2 or higher of the capnp executable \
                 is installed on your system. See https://capnproto.org/install.html",
                error))})
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use common::{Result, Id, Op2, Const};
use explicit;
use implicit;
use env;
use hindley_milner;

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Imm {
    Bool(bool),
    Int(i64),
    Var(Id),
//    Fun(Id, Box<Expr>),
//    Fix(Id, Box<Expr>),
//    Star,
//    V,
}

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Op {
    Op2(Op2, Box<Imm>, Box<Imm>),
//    MkArray(Box<Imm>, Box<Imm>),
//    GetArray(Box<Imm>, Box<Imm>),
//    SetArray(Box<Imm>, Box<Imm>, Box<Imm>),
    Imm(Imm),
}
//    WellFormed(Imm), // Var-only

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Expr {
//    If(Box<Imm>, Box<Imm>, Box<Imm>),
//    App(Box<Imm>, Box<Imm>),
    Let(Id, Box<Expr>, Box<Expr>),
    Op(Op),
}

struct ConvEnv {
    //env: HashMap<Id, explicit::Type>,
    next_id: i32,
}

impl ConvEnv {
    fn new() -> ConvEnv {
        ConvEnv {
            //env: HashMap::new(),
            next_id: 0,
        }
    }

    fn tmp(&self) -> (ConvEnv, Id) {
        let id = self.next_id;
        let c = ConvEnv{
            //env: self.env.clone(),
            next_id: self.next_id+1,
        };

        (c, format!("!tmp!{}", id))
    }
}

fn op(cenv: ConvEnv, e: &explicit::Expr) -> (ConvEnv, Op) {
    use typed::Expr as E;
    match *e {
        E::Const(Const::Bool(c)) => (cenv, Op::Imm(Imm::Bool(c))),
        E::Const(Const::Int(c)) => (cenv, Op::Imm(Imm::Int(c))),
        _ => {
            panic!("TODO: implement term for {:?}", e);
        }
    }
}

    // 1:1 translation -- can't fail
fn expr<F>(cenv: ConvEnv, e: &explicit::Expr, k: F) -> (ConvEnv, Expr)
    where F: FnOnce(ConvEnv, Expr) -> (ConvEnv, Expr) {

    use self::Imm as I;
    use typed::Expr as E;
    use self::Op::*;
    use self::Expr::*;

    match *e {
        E::Const(_) => {
            let (cenv, eop) = op(cenv, e);
            (cenv, Op(eop))
        }
        E::Op2(op, ref l, ref r) => {
            expr(cenv, l, |cenv, ll| {
                let (cenv, tmp1) = cenv.tmp();
                let (cenv, outer_expr) = expr(cenv, r, |cenv, rr| {
                    let (cenv, tmp2) = cenv.tmp();
                    // value to pass to the continuation
                    let val = Op(Op2(op,
                                     box I::Var(tmp1.clone()),
                                     box I::Var(tmp2.clone())));
                    // our inner expression is whatever the
                    // continuation says it is.
                    let (cenv, inner_expr) = k(cenv, val);
                    (cenv, Let(tmp2, box rr, box inner_expr))
                });
                (cenv, Let(tmp1, box ll, box outer_expr))
            })
        }
        _ => {
            panic!("TODO: implement expr for {:?}", e);
        }
    }
        // E::Op2(op, ref e1, ref e2) => {
        //     let (n, e1, _) = convert(n, env, renamed, e1);
        //     let (n, e2, _) = convert(n, env, renamed, e2);
        //     (n, I::Op2(op, box e1, box e2), explicit::opty(op))
        // }
        // E::If(ref e1, ref e2, ref e3) => {
        //     let (n, e1, _) = convert(n, env, renamed, e1);
        //     let (n, e2, t) = convert(n, env, renamed, e2);
        //     let (n, e3, _) = convert(n, env, renamed, e3);
        //     (n, I::If(box e1, box e2, box e3), t)
        // }
        // E::Var(ref x) => {
        //     let αx = renamed.get(x).unwrap();
        //     (n, I::Var(αx.clone()), env.get(αx).unwrap().clone())
        // }
        // E::Let(ref id, ref e1, ref e2) => {
        //     let mut renamed = renamed.clone();
        //     let (n, αid) = (n+1, format!("{}!a{}", id, n));

        //     let (n, e1, t1) = convert(n, env, &renamed, e1);

        //     renamed.insert(id.clone(), αid.clone());
        //     env.insert(αid.clone(), t1);

        //     let (n, e2, t2) = convert(n, env, &renamed, e2);
        //     (n, I::Let(αid, box e1, box e2), t2)
        // }
        // E::Fun(ref id, ref t1, ref e) => {
        //     let mut renamed = renamed.clone();
        //     let (n, αid) = (n+1, format!("{}!a{}", id, n));

        //     renamed.insert(id.clone(), αid.clone());
        //     env.insert(αid.clone(), t1.clone());

        //     let (n, e, t2) = convert(n, env, &renamed, e);

        //     (n, I::Fun(αid, box e), Type::TFun(box t1.clone(), box t2))
        // }
        // E::Fix(ref id, ref t1, ref e) => {
        //     let mut renamed = renamed.clone();
        //     let (n, αid) = (n+1, format!("{}!a{}", id, n));

        //     renamed.insert(id.clone(), αid.clone());
        //     env.insert(αid.clone(), t1.clone());

        //     let (n, e, t2) = convert(n, env, &renamed, e);

        //     (n, I::Fix(αid, box e), t2)
        // }
        // E::App(ref e1, ref e2) => {
        //     let (n, e1, t1) = convert(n, env, renamed, e1);
        //     let (n, e2, _) = convert(n, env, renamed, e2);
        //     let t = match t1 {
        //         Type::TFun(_, t2) => *t2,
        //         _ => panic!("expected TFun, not {:?}", t1),
        //     };
        //     (n, I::App(box e1, box e2), t)
        // }
        // E::MkArray(ref sz, ref val) => {
        //     let (n, sz, _) = convert(n, env, renamed, sz);
        //     let (n, val, _) = convert(n, env, renamed, val);
        //     (n, I::MkArray(box sz, box val), Type::TIntArray)
        // }
        // E::GetArray(ref id, ref idx) => {
        //     let (n, id, _) = convert(n, env, renamed, id);
        //     let (n, idx, _) = convert(n, env, renamed, idx);
        //     (n, I::GetArray(box id, box idx), Type::TInt)
        // }
        // E::SetArray(ref id, ref idx, ref v) => {
        //     let (n, id, _) = convert(n, env, renamed, id);
        //     let (n, idx, _) = convert(n, env, renamed, idx);
        //     let (n, v, _) = convert(n, env, renamed, v);
        //     (n, I::SetArray(box id, box idx, box v), Type::TIntArray)
        // }
}

fn anf(implicit_expr: &implicit::Expr) -> Result<(Expr, HashMap<Id, explicit::Type>)> {

    let explicit_expr = hindley_milner::infer(implicit_expr)?;
    let (α_expr, env) = env::extract(&explicit_expr);
    // println!("α-implicit: {:?}\n", α_expr);
    // println!("Γ         : {:?}\n", env);

    let cenv = ConvEnv::new();
    let (_, expr) = expr(cenv, &α_expr, |ce, x| (ce, x));

    Ok((expr, env))
    // step 1 -- arithmatic + let bindings
    // step 2 -- conds + boolean vals
    // step 3 -- arrays
    // step 4 -- closures

// (define (Value? M)
//   (match M
//     [`(quote ,_)         #t]
//     [(? number?)         #t]
//     [(? boolean?)        #t]
//     [(? string?)         #t]
//     [(? char?)           #t]
//     [(? symbol?)         #t]
//     [(or '+ '- '* '/ '=) #t]
//     [else                #f]))

// (define (normalize-term M) (normalize M (λ (x) x)))

// (define (normalize M k)
//   (match M
//     [`(λ ,params ,body)
//       (k `(λ ,params ,(normalize-term body)))]

//     [`(let ([,x ,M1]) ,M2)
//       (normalize M1 (λ (N1)
//        `(let ([,x ,N1])
//          ,(normalize M2 k))))]

//     [`(if ,M1 ,M2 ,M3)
//       (normalize-name M1 (λ (t)
//        (k `(if ,t ,(normalize-term M2)
//                   ,(normalize-term M3)))))]

//     [`(,Fn . ,M*)
//       (normalize-name Fn (λ (t)
//        (normalize-name* M* (λ (t*)
//         (k `(,t . ,t*))))))]

//     [(? Value?)             (k M)]))

// (define (normalize-name M k)
//   (normalize M (λ (N)
//     (if (Value? N) (k N)
//         (let ([t (gensym)])
//          `(let ([,t ,N]) ,(k t)))))))

// (define (normalize-name* M* k)
//   (if (null? M*)
//       (k '())
//       (normalize-name (car M*) (λ (t)
//        (normalize-name* (cdr M*) (λ (t*)
//         (k `(,t . ,t*))))))))

}

macro_rules! test_anf(
    ($s:expr, $ae:expr) => { {
        use implicit_parse;
        use tok::Tokenizer;
        use std;
        let s = $s;
        let tokenizer = Tokenizer::new(&s);
        let iexpr = match implicit_parse::parse_Program(&s, tokenizer) {
            Ok(iexpr) => iexpr,
            Err(e) => {
                die!("parse_Program({}): {:?}", $s, e);
            }
        };
        let anf_expr = match anf(&iexpr) {
            Ok((anf_expr, _)) => anf_expr,
            Err(e) => {
                die!("anf: {:?}", e);
            }
        };
        if anf_expr != $ae {
            die!("mismatch {:?} != {:?}", anf_expr, $ae);
        }
    } }
);

#[test]
fn anf_transforms() {
    use common::Op2 as O;
    use self::Imm as I;
    use self::Op::*;
    use self::Expr::*;

    test_anf!(
        "-22",
        Op(Imm(I::Int(-22))));
    test_anf!(
        "2+3",
        Let(String::from("!tmp!0"),
            box Op(Op2(O::Add, box I::Int(2), box I::Int(3))),
            box Op(Imm(I::Var(String::from("!tmp!0"))))));
}
<commit_msg>explicitly type closures<commit_after>use std::collections::HashMap;

use common::{Result, Id, Op2, Const};
use explicit;
use implicit;
use env;
use hindley_milner;

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Imm {
    Bool(bool),
    Int(i64),
    Var(Id),
//    Fun(Id, Box<Expr>),
//    Fix(Id, Box<Expr>),
//    Star,
//    V,
}

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Op {
    Op2(Op2, Box<Imm>, Box<Imm>),
//    MkArray(Box<Imm>, Box<Imm>),
//    GetArray(Box<Imm>, Box<Imm>),
//    SetArray(Box<Imm>, Box<Imm>, Box<Imm>),
    Imm(Imm),
}
//    WellFormed(Imm), // Var-only

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Expr {
//    If(Box<Imm>, Box<Imm>, Box<Imm>),
//    App(Box<Imm>, Box<Imm>),
    Let(Id, Box<Expr>, Box<Expr>),
    Op(Op),
}

struct ConvEnv {
    //env: HashMap<Id, explicit::Type>,
    next_id: i32,
}

impl ConvEnv {
    fn new() -> ConvEnv {
        ConvEnv {
            //env: HashMap::new(),
            next_id: 0,
        }
    }

    fn tmp(&self) -> (ConvEnv, Id) {
        let id = self.next_id;
        let c = ConvEnv{
            //env: self.env.clone(),
            next_id: self.next_id+1,
        };

        (c, format!("!tmp!{}", id))
    }
}

fn op(cenv: ConvEnv, e: &explicit::Expr) -> (ConvEnv, Op) {
    use typed::Expr as E;
    match *e {
        E::Const(Const::Bool(c)) => (cenv, Op::Imm(Imm::Bool(c))),
        E::Const(Const::Int(c)) => (cenv, Op::Imm(Imm::Int(c))),
        _ => {
            panic!("TODO: implement term for {:?}", e);
        }
    }
}

    // 1:1 translation -- can't fail
fn expr<F>(cenv: ConvEnv, e: &explicit::Expr, k: F) -> (ConvEnv, Expr)
    where F: FnOnce(ConvEnv, &Expr) -> (ConvEnv, Expr) {

    use self::Imm as I;
    use typed::Expr as E;
    use self::Op::*;
    use self::Expr::*;

    match *e {
        E::Const(_) => {
            let (cenv, eop) = op(cenv, e);
            (cenv, Op(eop))
        }
        E::Op2(op, ref l, ref r) => {
            expr(cenv, l, |cenv: ConvEnv, ll: &Expr| {
                let (cenv, tmp1) = cenv.tmp();
                let (cenv, outer_expr) = expr(cenv, r, |cenv: ConvEnv, rr: &Expr| {
                    let (cenv, tmp2) = cenv.tmp();
                    // value to pass to the continuation
                    let val = Op(Op2(op,
                                     box I::Var(tmp1.clone()),
                                     box I::Var(tmp2.clone())));
                    // our inner expression is whatever the
                    // continuation says it is.
                    let (cenv, inner_expr) = k(cenv, &val);
                    (cenv, Let(tmp2, box rr.clone(), box inner_expr))
                });
                (cenv, Let(tmp1, box ll.clone(), box outer_expr))
            })
        }
        _ => {
            panic!("TODO: implement expr for {:?}", e);
        }
    }
        // E::Op2(op, ref e1, ref e2) => {
        //     let (n, e1, _) = convert(n, env, renamed, e1);
        //     let (n, e2, _) = convert(n, env, renamed, e2);
        //     (n, I::Op2(op, box e1, box e2), explicit::opty(op))
        // }
        // E::If(ref e1, ref e2, ref e3) => {
        //     let (n, e1, _) = convert(n, env, renamed, e1);
        //     let (n, e2, t) = convert(n, env, renamed, e2);
        //     let (n, e3, _) = convert(n, env, renamed, e3);
        //     (n, I::If(box e1, box e2, box e3), t)
        // }
        // E::Var(ref x) => {
        //     let αx = renamed.get(x).unwrap();
        //     (n, I::Var(αx.clone()), env.get(αx).unwrap().clone())
        // }
        // E::Let(ref id, ref e1, ref e2) => {
        //     let mut renamed = renamed.clone();
        //     let (n, αid) = (n+1, format!("{}!a{}", id, n));

        //     let (n, e1, t1) = convert(n, env, &renamed, e1);

        //     renamed.insert(id.clone(), αid.clone());
        //     env.insert(αid.clone(), t1);

        //     let (n, e2, t2) = convert(n, env, &renamed, e2);
        //     (n, I::Let(αid, box e1, box e2), t2)
        // }
        // E::Fun(ref id, ref t1, ref e) => {
        //     let mut renamed = renamed.clone();
        //     let (n, αid) = (n+1, format!("{}!a{}", id, n));

        //     renamed.insert(id.clone(), αid.clone());
        //     env.insert(αid.clone(), t1.clone());

        //     let (n, e, t2) = convert(n, env, &renamed, e);

        //     (n, I::Fun(αid, box e), Type::TFun(box t1.clone(), box t2))
        // }
        // E::Fix(ref id, ref t1, ref e) => {
        //     let mut renamed = renamed.clone();
        //     let (n, αid) = (n+1, format!("{}!a{}", id, n));

        //     renamed.insert(id.clone(), αid.clone());
        //     env.insert(αid.clone(), t1.clone());

        //     let (n, e, t2) = convert(n, env, &renamed, e);

        //     (n, I::Fix(αid, box e), t2)
        // }
        // E::App(ref e1, ref e2) => {
        //     let (n, e1, t1) = convert(n, env, renamed, e1);
        //     let (n, e2, _) = convert(n, env, renamed, e2);
        //     let t = match t1 {
        //         Type::TFun(_, t2) => *t2,
        //         _ => panic!("expected TFun, not {:?}", t1),
        //     };
        //     (n, I::App(box e1, box e2), t)
        // }
        // E::MkArray(ref sz, ref val) => {
        //     let (n, sz, _) = convert(n, env, renamed, sz);
        //     let (n, val, _) = convert(n, env, renamed, val);
        //     (n, I::MkArray(box sz, box val), Type::TIntArray)
        // }
        // E::GetArray(ref id, ref idx) => {
        //     let (n, id, _) = convert(n, env, renamed, id);
        //     let (n, idx, _) = convert(n, env, renamed, idx);
        //     (n, I::GetArray(box id, box idx), Type::TInt)
        // }
        // E::SetArray(ref id, ref idx, ref v) => {
        //     let (n, id, _) = convert(n, env, renamed, id);
        //     let (n, idx, _) = convert(n, env, renamed, idx);
        //     let (n, v, _) = convert(n, env, renamed, v);
        //     (n, I::SetArray(box id, box idx, box v), Type::TIntArray)
        // }
}

fn anf(implicit_expr: &implicit::Expr) -> Result<(Expr, HashMap<Id, explicit::Type>)> {

    let explicit_expr = hindley_milner::infer(implicit_expr)?;
    let (α_expr, env) = env::extract(&explicit_expr);
    // println!("α-implicit: {:?}\n", α_expr);
    // println!("Γ         : {:?}\n", env);

    let cenv = ConvEnv::new();
    let (_, expr) = expr(cenv, &α_expr, |ce, x| (ce, x.clone()));

    Ok((expr, env))
    // step 1 -- arithmatic + let bindings
    // step 2 -- conds + boolean vals
    // step 3 -- arrays
    // step 4 -- closures

// (define (Value? M)
//   (match M
//     [`(quote ,_)         #t]
//     [(? number?)         #t]
//     [(? boolean?)        #t]
//     [(? string?)         #t]
//     [(? char?)           #t]
//     [(? symbol?)         #t]
//     [(or '+ '- '* '/ '=) #t]
//     [else                #f]))

// (define (normalize-term M) (normalize M (λ (x) x)))

// (define (normalize M k)
//   (match M
//     [`(λ ,params ,body)
//       (k `(λ ,params ,(normalize-term body)))]

//     [`(let ([,x ,M1]) ,M2)
//       (normalize M1 (λ (N1)
//        `(let ([,x ,N1])
//          ,(normalize M2 k))))]

//     [`(if ,M1 ,M2 ,M3)
//       (normalize-name M1 (λ (t)
//        (k `(if ,t ,(normalize-term M2)
//                   ,(normalize-term M3)))))]

//     [`(,Fn . ,M*)
//       (normalize-name Fn (λ (t)
//        (normalize-name* M* (λ (t*)
//         (k `(,t . ,t*))))))]

//     [(? Value?)             (k M)]))

// (define (normalize-name M k)
//   (normalize M (λ (N)
//     (if (Value? N) (k N)
//         (let ([t (gensym)])
//          `(let ([,t ,N]) ,(k t)))))))

// (define (normalize-name* M* k)
//   (if (null? M*)
//       (k '())
//       (normalize-name (car M*) (λ (t)
//        (normalize-name* (cdr M*) (λ (t*)
//         (k `(,t . ,t*))))))))

}

macro_rules! test_anf(
    ($s:expr, $ae:expr) => { {
        use implicit_parse;
        use tok::Tokenizer;
        use std;
        let s = $s;
        let tokenizer = Tokenizer::new(&s);
        let iexpr = match implicit_parse::parse_Program(&s, tokenizer) {
            Ok(iexpr) => iexpr,
            Err(e) => {
                die!("parse_Program({}): {:?}", $s, e);
            }
        };
        let anf_expr = match anf(&iexpr) {
            Ok((anf_expr, _)) => anf_expr,
            Err(e) => {
                die!("anf: {:?}", e);
            }
        };
        if anf_expr != $ae {
            die!("mismatch {:?} != {:?}", anf_expr, $ae);
        }
    } }
);

#[test]
fn anf_transforms() {
    use common::Op2 as O;
    use self::Imm as I;
    use self::Op::*;
    use self::Expr::*;

    test_anf!(
        "-22",
        Op(Imm(I::Int(-22))));
    test_anf!(
        "2+3",
        Let(String::from("!tmp!0"),
            box Op(Op2(O::Add, box I::Int(2), box I::Int(3))),
            box Op(Imm(I::Var(String::from("!tmp!0"))))));
}
<|endoftext|>


<commit_before>
import rustrt::sbuf;
import uint::le;
// export sbuf;
// export rustrt;
// export eq;
// export lteq;
// export hash;
// export is_utf8;
// export is_ascii;
export alloc;
// export byte_len;
// export buf;
// export bytes;
// export unsafe_from_byte;
// export str_from_cstr;
// export str_from_buf;
// export push_utf8_bytes;
// export from_char;
// export from_chars;
// export utf8_char_width;
// export char_range_at;
// export char_at;
// export char_len;
// export to_chars;
// export push_char;
// export pop_char;
// export shift_char;
// export unshift_char;
// export refcount;
// export index;
// export rindex;
// export find;
// export starts_with;
// export ends_with;
// export substr;
// export slice;
// export shift_byte;
// export pop_byte;
// export push_byte;
// export unshift_byte;
// export split;
// export concat;
// export connect;
// export to_upper;
// export safe_slice;
export unsafe_from_bytes;
// export is_empty;
// export is_not_empty;
// export is_whitespace;
// export replace;
// export char_slice;
// export trim_left;
// export trim_right;
// export trim;

native "rust" mod rustrt {
    type sbuf;
    fn str_buf(s: str) -> sbuf;
    fn str_byte_len(s: str) -> uint;
    fn str_alloc(n_bytes: uint) -> str;
    fn str_from_vec(b: &[mutable? u8]) -> str;
    fn str_from_cstr(cstr: sbuf) -> str;
    fn str_from_buf(buf: sbuf, len: uint) -> str;
    fn str_push_byte(s: str, byte: uint) -> str;
    fn str_slice(s: str, begin: uint, end: uint) -> str;
    fn refcount<T>(s: str) -> uint;
}

fn eq(a: &str, b: &str) -> bool {
    let i: uint = byte_len(a);
    if byte_len(b) != i { ret false; }
    while i > 0u {
        i -= 1u;
        let cha = a[i];
        let chb = b[i];
        if cha != chb { ret false; }
    }
    ret true;
}

fn lteq(a: &str, b: &str) -> bool {
    let i: uint = byte_len(a);
    let j: uint = byte_len(b);
    let n: uint = i;
    if j < n { n = j; }
    let x: uint = 0u;
    while x < n {
        let cha = a[x];
        let chb = b[x];
        if cha < chb { ret true; } else if cha > chb { ret false; }
        x += 1u;
    }
    ret i <= j;
}

fn hash(s: &str) -> uint {
    // djb hash.
    // FIXME: replace with murmur.

    let u: uint = 5381u;
    for c: u8 in s { u *= 33u; u += c as uint; }
    ret u;
}

// UTF-8 tags and ranges
const tag_cont_u8: u8 = 128u8;

const tag_cont: uint = 128u;

const max_one_b: uint = 128u;

const tag_two_b: uint = 192u;

const max_two_b: uint = 2048u;

const tag_three_b: uint = 224u;

const max_three_b: uint = 65536u;

const tag_four_b: uint = 240u;

const max_four_b: uint = 2097152u;

const tag_five_b: uint = 248u;

const max_five_b: uint = 67108864u;

const tag_six_b: uint = 252u;

fn is_utf8(v: &[u8]) -> bool {
    let i = 0u;
    let total = vec::len::<u8>(v);
    while i < total {
        let chsize = utf8_char_width(v[i]);
        if chsize == 0u { ret false; }
        if i + chsize > total { ret false; }
        i += 1u;
        while chsize > 1u {
            if v[i] & 192u8 != tag_cont_u8 { ret false; }
            i += 1u;
            chsize -= 1u;
        }
    }
    ret true;
}

fn is_ascii(s: str) -> bool {
    let i: uint = byte_len(s);
    while i > 0u { i -= 1u; if s[i] & 128u8 != 0u8 { ret false; } }
    ret true;
}

fn alloc(n_bytes: uint) -> str { ret rustrt::str_alloc(n_bytes); }

/// Returns true if the string has length 0
pure fn is_empty(s: str) -> bool { for c: u8 in s { ret false; } ret true; }

/// Returns true if the string has length greater than 0
pure fn is_not_empty(s: str) -> bool { !is_empty(s) }

fn is_whitespace(s: str) -> bool {
    let i = 0u;
    let len = char_len(s);
    while i < len {
        if !char::is_whitespace(char_at(s, i)) { ret false; }
        i += 1u
    }
    ret true;
}

// Returns the number of bytes (a.k.a. UTF-8 code units) in s.
// Contrast with a function that would return the number of code
// points (char's), combining character sequences, words, etc.  See
// http://icu-project.org/apiref/icu4c/classBreakIterator.html for a
// way to implement those.
fn byte_len(s: str) -> uint { ret rustrt::str_byte_len(s); }

fn buf(s: &str) -> sbuf { ret rustrt::str_buf(s); }

fn bytes(s: str) -> [u8] {
    let sbuffer = buf(s);
    let ptr = unsafe::reinterpret_cast(sbuffer);
    ret vec::unsafe::from_buf(ptr, byte_len(s));
}

fn unsafe_from_bytes(v: &[mutable? u8]) -> str {
    ret rustrt::str_from_vec(v);
}

fn unsafe_from_byte(u: u8) -> str { ret rustrt::str_from_vec([u]); }

fn str_from_cstr(cstr: sbuf) -> str { ret rustrt::str_from_cstr(cstr); }

fn str_from_buf(buf: sbuf, len: uint) -> str {
    ret rustrt::str_from_buf(buf, len);
}

fn push_utf8_bytes(s: &mutable str, ch: char) {
    let code = ch as uint;
    if code < max_one_b {
        s = rustrt::str_push_byte(s, code);
    } else if code < max_two_b {
        s = rustrt::str_push_byte(s, code >> 6u & 31u | tag_two_b);
        s = rustrt::str_push_byte(s, code & 63u | tag_cont);
    } else if code < max_three_b {
        s = rustrt::str_push_byte(s, code >> 12u & 15u | tag_three_b);
        s = rustrt::str_push_byte(s, code >> 6u & 63u | tag_cont);
        s = rustrt::str_push_byte(s, code & 63u | tag_cont);
    } else if code < max_four_b {
        s = rustrt::str_push_byte(s, code >> 18u & 7u | tag_four_b);
        s = rustrt::str_push_byte(s, code >> 12u & 63u | tag_cont);
        s = rustrt::str_push_byte(s, code >> 6u & 63u | tag_cont);
        s = rustrt::str_push_byte(s, code & 63u | tag_cont);
    } else if code < max_five_b {
        s = rustrt::str_push_byte(s, code >> 24u & 3u | tag_five_b);
        s = rustrt::str_push_byte(s, code >> 18u & 63u | tag_cont);
        s = rustrt::str_push_byte(s, code >> 12u & 63u | tag_cont);
        s = rustrt::str_push_byte(s, code >> 6u & 63u | tag_cont);
        s = rustrt::str_push_byte(s, code & 63u | tag_cont);
    } else {
        s = rustrt::str_push_byte(s, code >> 30u & 1u | tag_six_b);
        s = rustrt::str_push_byte(s, code >> 24u & 63u | tag_cont);
        s = rustrt::str_push_byte(s, code >> 18u & 63u | tag_cont);
        s = rustrt::str_push_byte(s, code >> 12u & 63u | tag_cont);
        s = rustrt::str_push_byte(s, code >> 6u & 63u | tag_cont);
        s = rustrt::str_push_byte(s, code & 63u | tag_cont);
    }
}

fn from_char(ch: char) -> str {
    let buf = "";
    push_utf8_bytes(buf, ch);
    ret buf;
}

fn from_chars(chs: &[char]) -> str {
    let buf = "";
    for ch: char in chs { push_utf8_bytes(buf, ch); }
    ret buf;
}

fn utf8_char_width(b: u8) -> uint {
    let byte: uint = b as uint;
    if byte < 128u { ret 1u; }
    if byte < 192u {
        ret 0u; // Not a valid start byte

    }
    if byte < 224u { ret 2u; }
    if byte < 240u { ret 3u; }
    if byte < 248u { ret 4u; }
    if byte < 252u { ret 5u; }
    ret 6u;
}

fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} {
    let b0 = s[i];
    let w = utf8_char_width(b0);
    assert (w != 0u);
    if w == 1u { ret {ch: b0 as char, next: i + 1u}; }
    let val = 0u;
    let end = i + w;
    i += 1u;
    while i < end {
        let byte = s[i];
        assert (byte & 192u8 == tag_cont_u8);
        val <<= 6u;
        val += byte & 63u8 as uint;
        i += 1u;
    }
    // Clunky way to get the right bits from the first byte. Uses two shifts,
    // the first to clip off the marker bits at the left of the byte, and then
    // a second (as uint) to get it to the right position.

    val += (b0 << (w + 1u as u8) as uint) << (w - 1u) * 6u - w - 1u;
    ret {ch: val as char, next: i};
}

fn char_at(s: str, i: uint) -> char { ret char_range_at(s, i).ch; }

fn char_len(s: str) -> uint {
    let i = 0u;
    let len = 0u;
    let total = byte_len(s);
    while i < total {
        let chsize = utf8_char_width(s[i]);
        assert (chsize > 0u);
        len += 1u;
        i += chsize;
    }
    assert (i == total);
    ret len;
}

fn to_chars(s: str) -> [char] {
    let buf: [char] = [];
    let i = 0u;
    let len = byte_len(s);
    while i < len {
        let cur = char_range_at(s, i);
        buf += [cur.ch];
        i = cur.next;
    }
    ret buf;
}

fn push_char(s: &mutable str, ch: char) { s += from_char(ch); }

fn pop_char(s: &mutable str) -> char {
    let end = byte_len(s);
    while end > 0u && s[end - 1u] & 192u8 == tag_cont_u8 { end -= 1u; }
    assert (end > 0u);
    let ch = char_at(s, end - 1u);
    s = substr(s, 0u, end - 1u);
    ret ch;
}

fn shift_char(s: &mutable str) -> char {
    let r = char_range_at(s, 0u);
    s = substr(s, r.next, byte_len(s) - r.next);
    ret r.ch;
}

fn unshift_char(s: &mutable str, ch: char) { s = from_char(ch) + s; }

fn refcount(s: str) -> uint {
    let r = rustrt::refcount::<u8>(s);
    if r == dbg::const_refcount { ret r; } else { ret r - 1u; }
}

// Standard bits from the world of string libraries.
fn index(s: str, c: u8) -> int {
    let i: int = 0;
    for k: u8 in s { if k == c { ret i; } i += 1; }
    ret -1;
}

fn rindex(s: str, c: u8) -> int {
    let n: int = byte_len(s) as int;
    while n >= 0 { if s[n] == c { ret n; } n -= 1; }
    ret n;
}

fn find(haystack: str, needle: str) -> int {
    let haystack_len: int = byte_len(haystack) as int;
    let needle_len: int = byte_len(needle) as int;
    if needle_len == 0 { ret 0; }
    fn match_at(haystack: &str, needle: &str, i: int) -> bool {
        let j: int = i;
        for c: u8 in needle { if haystack[j] != c { ret false; } j += 1; }
        ret true;
    }
    let i: int = 0;
    while i <= haystack_len - needle_len {
        if match_at(haystack, needle, i) { ret i; }
        i += 1;
    }
    ret -1;
}

fn starts_with(haystack: str, needle: str) -> bool {
    let haystack_len: uint = byte_len(haystack);
    let needle_len: uint = byte_len(needle);
    if needle_len == 0u { ret true; }
    if needle_len > haystack_len { ret false; }
    ret eq(substr(haystack, 0u, needle_len), needle);
}

fn ends_with(haystack: str, needle: str) -> bool {
    let haystack_len: uint = byte_len(haystack);
    let needle_len: uint = byte_len(needle);
    ret if needle_len == 0u {
            true
        } else if needle_len > haystack_len {
            false
        } else {
            eq(substr(haystack, haystack_len - needle_len, needle_len),
               needle)
        };
}

fn substr(s: str, begin: uint, len: uint) -> str {
    ret slice(s, begin, begin + len);
}

fn slice(s: str, begin: uint, end: uint) -> str {
    // FIXME: Typestate precondition

    assert (begin <= end);
    assert (end <= byte_len(s));
    ret rustrt::str_slice(s, begin, end);
}

fn safe_slice(s: str, begin: uint, end: uint) : le(begin, end) -> str {
    // would need some magic to
    // make this a precondition
    assert (end <= byte_len(s));

    ret rustrt::str_slice(s, begin, end);
}

fn shift_byte(s: &mutable str) -> u8 {
    let len = byte_len(s);
    assert (len > 0u);
    let b = s[0];
    s = substr(s, 1u, len - 1u);
    ret b;
}

fn pop_byte(s: &mutable str) -> u8 {
    let len = byte_len(s);
    assert (len > 0u);
    let b = s[len - 1u];
    s = substr(s, 0u, len - 1u);
    ret b;
}

fn push_byte(s: &mutable str, b: u8) {
    s = rustrt::str_push_byte(s, b as uint);
}

fn unshift_byte(s: &mutable str, b: u8) {
    let rs = alloc(byte_len(s) + 1u);
    rs += unsafe_from_byte(b);
    rs += s;
    s = rs;
}

fn split(s: str, sep: u8) -> [str] {
    let v: [str] = [];
    let accum: str = "";
    let ends_with_sep: bool = false;
    for c: u8 in s {
        if c == sep {
            v += [accum];
            accum = "";
            ends_with_sep = true;
        } else { accum += unsafe_from_byte(c); ends_with_sep = false; }
    }
    if byte_len(accum) != 0u || ends_with_sep { v += [accum]; }
    ret v;
}

fn concat(v: &[str]) -> str {
    let s: str = "";
    for ss: str in v { s += ss; }
    ret s;
}

fn connect(v: &[str], sep: str) -> str {
    let s: str = "";
    let first: bool = true;
    for ss: str in v {
        if first { first = false; } else { s += sep; }
        s += ss;
    }
    ret s;
}

// FIXME: This only handles ASCII
fn to_upper(s: str) -> str {
    let outstr = "";
    let ascii_a = 'a' as u8;
    let ascii_z = 'z' as u8;
    let diff = 32u8;
    for byte: u8 in s {
        let next;
        if ascii_a <= byte && byte <= ascii_z {
            next = byte - diff;
        } else { next = byte; }
        push_byte(outstr, next);
    }
    ret outstr;
}

// FIXME: This is super-inefficient
fn replace(s: str, from: str, to: str) : is_not_empty(from) -> str {
    // FIXME (694): Shouldn't have to check this
    check (is_not_empty(from));
    if byte_len(s) == 0u {
        ret "";
    } else if starts_with(s, from) {
        ret to + replace(slice(s, byte_len(from), byte_len(s)), from, to);
    } else {
        ret unsafe_from_byte(s[0]) +
                replace(slice(s, 1u, byte_len(s)), from, to);
    }
}

// FIXME: Also not efficient
fn char_slice(s: &str, begin: uint, end: uint) -> str {
    from_chars(vec::slice(to_chars(s), begin, end))
}

fn trim_left(s: &str) -> str {
    fn count_whities(s: &[char]) -> uint {
        let i = 0u;
        while i < vec::len(s) {
            if !char::is_whitespace(s[i]) { break; }
            i += 1u;
        }
        ret i;
    }
    let chars = to_chars(s);
    let whities = count_whities(chars);
    ret from_chars(vec::slice(chars, whities, vec::len(chars)));
}

fn trim_right(s: &str) -> str {
    fn count_whities(s: &[char]) -> uint {
        let i = vec::len(s);
        while 0u < i {
            if !char::is_whitespace(s[i - 1u]) { break; }
            i -= 1u;
        }
        ret i;
    }
    let chars = to_chars(s);
    let whities = count_whities(chars);
    ret from_chars(vec::slice(chars, 0u, whities));
}

fn trim(s: &str) -> str { trim_left(trim_right(s)) }

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Delete parts of std::str that are no longer exported. Issue #855<commit_after>export unsafe_from_bytes;

native "rust" mod rustrt {
    type sbuf;
    fn str_buf(s: str) -> sbuf;
    fn str_byte_len(s: str) -> uint;
    fn str_alloc(n_bytes: uint) -> str;
    fn str_from_vec(b: &[mutable? u8]) -> str;
    fn str_from_cstr(cstr: sbuf) -> str;
    fn str_from_buf(buf: sbuf, len: uint) -> str;
    fn str_push_byte(s: str, byte: uint) -> str;
    fn str_slice(s: str, begin: uint, end: uint) -> str;
    fn refcount<T>(s: str) -> uint;
}

fn unsafe_from_bytes(v: &[mutable? u8]) -> str {
    ret rustrt::str_from_vec(v);
}
<|endoftext|>


<commit_before>use std::env;
use std::io;
use std::io::prelude::*;
use std::fs::File;

fn read_file(filename:String) -> Result<String, io::Error>{
    let mut file = try!(File::open(filename));
    let mut content = String::new();
    try!(file.read_to_string(&mut content));
    Ok(content)
}

fn main() {
    let args:Vec<String> = env::args().collect();

    if args.len() > 1{
        println!("{}", match read_file(args[1].clone()){
            Ok(content) => content,
            Err(reason) => panic!(reason)
        });
    }
}
<commit_msg>updated with command line args retrieval idiom<commit_after>use std::env;
use std::io;
use std::io::prelude::*;
use std::fs::File;

fn read_file(filename:String) -> Result<String, io::Error>{
    let mut file = try!(File::open(filename));
    let mut content = String::new();
    try!(file.read_to_string(&mut content));
    Ok(content)
}

fn main() {
    let mut args = env::args();
    if let Some(file) = args.nth(1) {
        println!("{}", match read_file(file.clone()){
            Ok(content) => content,
            Err(reason) => panic!(reason)
        });
    }
}
<|endoftext|>


<commit_before>extern crate tiny_http;
extern crate multipart;

use multipart::server::{Multipart, Entries, SaveResult};
use tiny_http::{Response, StatusCode, Request};
fn main() {
    // Starting a server on `localhost:80`
    let server = tiny_http::Server::http("localhost:80").unwrap();
    loop {
        // This blocks until the next request is received
        let mut request = server.recv().unwrap();
        process_multipart(&mut request).unwrap();

        // Answering with an HTTP OK and a string
        let response_string = "Multipart data is received!".as_bytes();
        let response = Response::new(StatusCode(200), vec![], response_string, Some(response_string.len()), None);
        request.respond(response).unwrap();
    }
}

fn process_multipart(request: &mut Request) -> Result<(), Error> {
    // Getting a multipart reader wrapper
    let mut multipart = Multipart::from_request(request).unwrap();
    // Fetching all data and processing it
    match multipart.save_all() {
        SaveResult::Full(entries) => process_entries(entries),
        SaveResult::Partial(entries, error) => {
            try!(process_entries(entries));
            Err(error)
        },
        SaveResult::Error(error) => Err(error)
    }
}
use std::fs::File;
use std::io::{Error, Read};
fn process_entries(entries: Entries) -> Result<(), Error> {
    for (name, field) in entries.fields {
        println!(r#"Field "{}": "{}""#, name, field);
    }

    for (name, savedfile) in entries.files {
        let filename = match savedfile.filename {
            Some(s) => s,
            None => "None".into()
        };
        let mut file = try!(File::open(savedfile.path));
        let mut contents = String::new();
        try!(file.read_to_string(&mut contents));

        println!(r#"Field "{}" is file "{}":"#, name, filename);
        println!("{}", contents);
    }
    Ok(())
}
<commit_msg>Run cargo fmt<commit_after>extern crate tiny_http;
extern crate multipart;

use multipart::server::{Multipart, Entries, SaveResult};
use tiny_http::{Response, StatusCode, Request};
fn main() {
    // Starting a server on `localhost:80`
    let server = tiny_http::Server::http("localhost:80").unwrap();
    loop {
        // This blocks until the next request is received
        let mut request = server.recv().unwrap();
        process_multipart(&mut request).unwrap();

        // Answering with an HTTP OK and a string
        let response_string = "Multipart data is received!".as_bytes();
        let response = Response::new(StatusCode(200),
                                     vec![],
                                     response_string,
                                     Some(response_string.len()),
                                     None);
        request.respond(response).unwrap();
    }
}

fn process_multipart(request: &mut Request) -> Result<(), Error> {
    // Getting a multipart reader wrapper
    let mut multipart = Multipart::from_request(request).unwrap();
    // Fetching all data and processing it
    match multipart.save_all() {
        SaveResult::Full(entries) => process_entries(entries),
        SaveResult::Partial(entries, error) => {
            try!(process_entries(entries));
            Err(error)
        }
        SaveResult::Error(error) => Err(error),
    }
}
use std::fs::File;
use std::io::{Error, Read};
fn process_entries(entries: Entries) -> Result<(), Error> {
    for (name, field) in entries.fields {
        println!(r#"Field "{}": "{}""#, name, field);
    }

    for (name, savedfile) in entries.files {
        let filename = match savedfile.filename {
            Some(s) => s,
            None => "None".into(),
        };
        let mut file = try!(File::open(savedfile.path));
        let mut contents = String::new();
        try!(file.read_to_string(&mut contents));

        println!(r#"Field "{}" is file "{}":"#, name, filename);
        println!("{}", contents);
    }
    Ok(())
}
<|endoftext|>


<commit_before>use structs::{ Map, SnakeInfo };
use util;

#[derive(PartialEq, Debug)]
pub enum Tile<'a> {
    Food { coordinate: (i32,i32) },
    Obstacle { coordinate: (i32,i32) },
    Empty { coordinate: (i32,i32) },
    SnakeHead { coordinate: (i32,i32), snake: &'a SnakeInfo },
    SnakeBody { coordinate: (i32,i32), snake: &'a SnakeInfo }
}

#[derive(Debug)]
pub enum Direction {
    Down,
    Up,
    Left,
    Right
}

pub fn direction_as_string(direction: &Direction) -> String {
    let s = match direction {
        &Direction::Down => "DOWN",
        &Direction::Up => "UP",
        &Direction::Left => "LEFT",
        &Direction::Right => "RIGHT"
    };

    String::from(s)
}

pub fn direction_as_movement_delta(direction: &Direction) -> (i32,i32) {
    match direction {
        &Direction::Down => (0, 1),
        &Direction::Up => (0, -1),
        &Direction::Left => (-1, 0),
        &Direction::Right => (1, 0)
    }
}

impl Map {
    pub fn get_snake_by_id<'a>(&'a self, id: &String) -> Option<&'a SnakeInfo> {
        self.snakeInfos.iter().find(|s| &s.id == id)
    }

    pub fn get_tile_at(&self, coordinate: (i32,i32)) -> Tile {
        let position = util::translate_coordinate(coordinate, self.width);
        let snake_at_tile = self.snakeInfos.iter().find(|s| s.positions.contains(&position));

        if self.obstaclePositions.contains(&position) {
            Tile::Obstacle { coordinate: coordinate }
        } else if self.foodPositions.contains(&position) {
            Tile::Food { coordinate: coordinate }
        } else if snake_at_tile.is_some() {
            let s = snake_at_tile.unwrap();
            if s.positions[0] == position {
                Tile::SnakeHead { coordinate: coordinate, snake: s }
            } else {
                Tile::SnakeBody { coordinate: coordinate, snake: s }
            }
        } else {
            Tile::Empty { coordinate: coordinate }
        }
    }

    pub fn is_tile_available_for_movement(&self, coordinate: (i32,i32)) -> bool {
        let tile = self.get_tile_at(coordinate);
        match tile {
            Tile::Empty { coordinate: _ } => true,
            Tile::Food { coordinate: _ } => true,
            _ => false
        }
    }

    pub fn can_snake_move_in_direction(&self, snake: &SnakeInfo, direction: Direction) -> bool {
        let (xd,yd) = direction_as_movement_delta(&direction);
        let (x,y) = util::translate_position(snake.positions[0], self.width);

        self.is_tile_available_for_movement((x+xd,y+yd))
    }

    #[allow(dead_code)]
    pub fn is_coordinate_out_of_bounds(&self, coordinate: (i32,i32)) -> bool {
        let (x,y) = coordinate;
        x < 0 || x >= self.width || y < 0 || y >= self.height
    }
}

#[cfg(test)]
mod test {
    use util::{ translate_coordinate };
    use maputil::{ Direction, Tile };
    use structs::{ Map, SnakeInfo };

    const MAP_WIDTH: i32 = 3;

    fn get_snake_one() -> SnakeInfo {
        SnakeInfo {
            name: String::from("1"),
            points: 0,
            tailProtectedForGameTicks: 0,
            positions: vec![translate_coordinate((1,1), MAP_WIDTH),
                            translate_coordinate((0,1), MAP_WIDTH)],
            id: String::from("1")
        }
    }

    fn get_snake_two() -> SnakeInfo {
        SnakeInfo {
            name: String::from("2"),
            points: 0,
            tailProtectedForGameTicks: 0,
            positions: vec![translate_coordinate((1,2), MAP_WIDTH)],
            id: String::from("2")
        }
    }

    // The map used for testing, 1 and 2 represents the snakes
    //yx012
    //0  F
    //1 11#
    //2  2
    fn get_test_map() -> Map {
        Map {
            type_: String::from("type"),
            width: MAP_WIDTH,
            height: MAP_WIDTH,
            worldTick: 0,
            snakeInfos: vec![get_snake_one(), get_snake_two()],
            foodPositions: vec![translate_coordinate((1,0),  MAP_WIDTH)],
            obstaclePositions: vec![translate_coordinate((2,1), MAP_WIDTH)],
            receivingPlayerId: Some(String::from("1"))
        }
    }

    #[test]
    fn snake_can_be_found_by_id() {
        let map = get_test_map();
        let id = map.receivingPlayerId.as_ref().unwrap();
        let s = map.get_snake_by_id(id);
        let found_id = &s.unwrap().id;
        assert_eq!(id, found_id);
    }

    #[test]
    fn tile_is_correctly_found() {
        let map = get_test_map();
        let snake_one = get_snake_one();
        let snake_two = get_snake_two();
        let tiles =
            vec![
                vec![Tile::Empty{ coordinate: (0,0) },
                     Tile::Food{ coordinate: (1,0) },
                     Tile::Empty{ coordinate: (2,0) }],
                vec![Tile::SnakeBody{ coordinate: (0,1), snake: &snake_one },
                     Tile::SnakeHead{ coordinate: (1,1), snake: &snake_one },
                     Tile::Obstacle{ coordinate: (2,1)}],
                vec![Tile::Empty{ coordinate: (0,2) },
                     Tile::SnakeHead{ coordinate: (1,2), snake: &snake_two },
                     Tile::Empty{ coordinate:(2,2) }]];
        for y in 0..map.width {
            for x in 0..map.height {
                assert_eq!(tiles[y as usize][x as usize],
                           map.get_tile_at((x,y)));
            }
        }
    }

    #[test]
    fn tile_is_correctly_marked_as_movable() {
        let map = get_test_map();
        let tiles = vec![vec![true, true, true],
                         vec![false, false, false],
                         vec![true, false, true]];

        for y in 0..map.height {
            for x in 0..map.width {
                assert_eq!(tiles[y as usize][x as usize],
                           map.is_tile_available_for_movement((x,y)));
            }
        }
    }

    #[test]
    fn can_snake_move_identifies_correctly() {
        let map = get_test_map();
        let id = map.receivingPlayerId.as_ref().unwrap();
        let snake = map.get_snake_by_id(id).unwrap();

        assert_eq!(true, map.can_snake_move_in_direction(&snake, Direction::Up));
        assert_eq!(false, map.can_snake_move_in_direction(&snake, Direction::Down));
        assert_eq!(false, map.can_snake_move_in_direction(&snake, Direction::Left));
        assert_eq!(false, map.can_snake_move_in_direction(&snake, Direction::Right));
    }
}
<commit_msg>Fix broken testcases<commit_after>use structs::{ Map, SnakeInfo };
use util;

#[derive(PartialEq, Debug)]
pub enum Tile<'a> {
    Food { coordinate: (i32,i32) },
    Obstacle { coordinate: (i32,i32) },
    Empty { coordinate: (i32,i32) },
    SnakeHead { coordinate: (i32,i32), snake: &'a SnakeInfo },
    SnakeBody { coordinate: (i32,i32), snake: &'a SnakeInfo }
}

#[derive(Debug)]
pub enum Direction {
    Down,
    Up,
    Left,
    Right
}

pub fn direction_as_string(direction: &Direction) -> String {
    let s = match direction {
        &Direction::Down => "DOWN",
        &Direction::Up => "UP",
        &Direction::Left => "LEFT",
        &Direction::Right => "RIGHT"
    };

    String::from(s)
}

pub fn direction_as_movement_delta(direction: &Direction) -> (i32,i32) {
    match direction {
        &Direction::Down => (0, 1),
        &Direction::Up => (0, -1),
        &Direction::Left => (-1, 0),
        &Direction::Right => (1, 0)
    }
}

impl Map {
    pub fn get_snake_by_id<'a>(&'a self, id: &String) -> Option<&'a SnakeInfo> {
        self.snakeInfos.iter().find(|s| &s.id == id)
    }

    pub fn get_tile_at(&self, coordinate: (i32,i32)) -> Tile {
        let position = util::translate_coordinate(coordinate, self.width);
        let snake_at_tile = self.snakeInfos.iter().find(|s| s.positions.contains(&position));

        if self.obstaclePositions.contains(&position) {
            Tile::Obstacle { coordinate: coordinate }
        } else if self.foodPositions.contains(&position) {
            Tile::Food { coordinate: coordinate }
        } else if snake_at_tile.is_some() {
            let s = snake_at_tile.unwrap();
            if s.positions[0] == position {
                Tile::SnakeHead { coordinate: coordinate, snake: s }
            } else {
                Tile::SnakeBody { coordinate: coordinate, snake: s }
            }
        } else {
            Tile::Empty { coordinate: coordinate }
        }
    }

    pub fn is_tile_available_for_movement(&self, coordinate: (i32,i32)) -> bool {
        let tile = self.get_tile_at(coordinate);
        match tile {
            Tile::Empty { coordinate: _ } => true,
            Tile::Food { coordinate: _ } => true,
            _ => false
        }
    }

    pub fn can_snake_move_in_direction(&self, snake: &SnakeInfo, direction: Direction) -> bool {
        let (xd,yd) = direction_as_movement_delta(&direction);
        let (x,y) = util::translate_position(snake.positions[0], self.width);

        self.is_tile_available_for_movement((x+xd,y+yd))
    }

    #[allow(dead_code)]
    pub fn is_coordinate_out_of_bounds(&self, coordinate: (i32,i32)) -> bool {
        let (x,y) = coordinate;
        x < 0 || x >= self.width || y < 0 || y >= self.height
    }
}

#[cfg(test)]
mod test {
    use util::{ translate_coordinate };
    use maputil::{ Direction, Tile };
    use structs::{ Map, SnakeInfo };

    const MAP_WIDTH: i32 = 3;

    fn get_snake_one() -> SnakeInfo {
        SnakeInfo {
            name: String::from("1"),
            points: 0,
            tailProtectedForGameTicks: 0,
            positions: vec![translate_coordinate((1,1), MAP_WIDTH),
                            translate_coordinate((0,1), MAP_WIDTH)],
            id: String::from("1")
        }
    }

    fn get_snake_two() -> SnakeInfo {
        SnakeInfo {
            name: String::from("2"),
            points: 0,
            tailProtectedForGameTicks: 0,
            positions: vec![translate_coordinate((1,2), MAP_WIDTH)],
            id: String::from("2")
        }
    }

    // The map used for testing, 1 and 2 represents the snakes
    //yx012
    //0  F
    //1 11#
    //2  2
    fn get_test_map() -> Map {
        Map {
            type_: String::from("type"),
            width: MAP_WIDTH,
            height: MAP_WIDTH,
            worldTick: 0,
            snakeInfos: vec![get_snake_one(), get_snake_two()],
            foodPositions: vec![translate_coordinate((1,0),  MAP_WIDTH)],
            obstaclePositions: vec![translate_coordinate((2,1), MAP_WIDTH)]
        }
    }

    #[test]
    fn snake_can_be_found_by_id() {
        let map = get_test_map();
        let id = &get_snake_one().id;
        let s = map.get_snake_by_id(id);
        let found_id = &s.unwrap().id;
        assert_eq!(id, found_id);
    }

    #[test]
    fn tile_is_correctly_found() {
        let map = get_test_map();
        let snake_one = get_snake_one();
        let snake_two = get_snake_two();
        let tiles =
            vec![
                vec![Tile::Empty{ coordinate: (0,0) },
                     Tile::Food{ coordinate: (1,0) },
                     Tile::Empty{ coordinate: (2,0) }],
                vec![Tile::SnakeBody{ coordinate: (0,1), snake: &snake_one },
                     Tile::SnakeHead{ coordinate: (1,1), snake: &snake_one },
                     Tile::Obstacle{ coordinate: (2,1)}],
                vec![Tile::Empty{ coordinate: (0,2) },
                     Tile::SnakeHead{ coordinate: (1,2), snake: &snake_two },
                     Tile::Empty{ coordinate:(2,2) }]];
        for y in 0..map.width {
            for x in 0..map.height {
                assert_eq!(tiles[y as usize][x as usize],
                           map.get_tile_at((x,y)));
            }
        }
    }

    #[test]
    fn tile_is_correctly_marked_as_movable() {
        let map = get_test_map();
        let tiles = vec![vec![true, true, true],
                         vec![false, false, false],
                         vec![true, false, true]];

        for y in 0..map.height {
            for x in 0..map.width {
                assert_eq!(tiles[y as usize][x as usize],
                           map.is_tile_available_for_movement((x,y)));
            }
        }
    }

    #[test]
    fn can_snake_move_identifies_correctly() {
        let map = get_test_map();
        let id = &get_snake_one().id;
        let snake = map.get_snake_by_id(id).unwrap();

        assert_eq!(true, map.can_snake_move_in_direction(&snake, Direction::Up));
        assert_eq!(false, map.can_snake_move_in_direction(&snake, Direction::Down));
        assert_eq!(false, map.can_snake_move_in_direction(&snake, Direction::Left));
        assert_eq!(false, map.can_snake_move_in_direction(&snake, Direction::Right));
    }
}
<|endoftext|>