<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 fmt;
use iter::IteratorExt;
use libc;
use mem;
use ops::Deref;
use slice::{self, SliceExt, AsSlice};
use string::String;
use vec::Vec;

/// A type representing a C-compatible string
///
/// This type serves the primary purpose of being able to generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
/// A `CString` is created from either a byte slice or a byte vector. After
/// being created, a `CString` predominately inherits all of its methods from
/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
/// `u8` slice can be obtained with the `as_bytes` method.  Slices produced from
/// a `CString` do *not* contain the trailing nul terminator unless otherwise
/// specified.
///
/// # Example
///
/// ```no_run
/// # extern crate libc;
/// # fn main() {
/// use std::ffi::CString;
/// use libc;
///
/// extern {
///     fn my_printer(s: *const libc::c_char);
/// }
///
/// let to_print = "Hello, world!";
/// let c_to_print = CString::from_slice(to_print.as_bytes());
/// unsafe {
///     my_printer(c_to_print.as_ptr());
/// }
/// # }
/// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct CString {
    inner: Vec<libc::c_char>,
}

impl CString {
    /// Create a new C-compatible string from a byte slice.
    ///
    /// This method will copy the data of the slice provided into a new
    /// allocation, ensuring that there is a trailing 0 byte.
    ///
    /// # Panics
    ///
    /// This function will panic if there are any 0 bytes already in the slice
    /// provided.
    pub fn from_slice(v: &[u8]) -> CString {
        CString::from_vec(v.to_vec())
    }

    /// Create a C-compatible string from a byte vector.
    ///
    /// This method will consume ownership of the provided vector, appending a 0
    /// byte to the end after verifying that there are no interior 0 bytes.
    ///
    /// # Panics
    ///
    /// This function will panic if there are any 0 bytes already in the vector
    /// provided.
    pub fn from_vec(v: Vec<u8>) -> CString {
        assert!(!v.iter().any(|&x| x == 0));
        unsafe { CString::from_vec_unchecked(v) }
    }

    /// Create a C-compatibel string from a byte vector without checking for
    /// interior 0 bytes.
    ///
    /// This method is equivalent to `from_vec` except that no runtime assertion
    /// is made that `v` contains no 0 bytes.
    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
        v.push(0);
        CString { inner: mem::transmute(v) }
    }

    /// Create a view into this C string which includes the trailing nul
    /// terminator at the end of the string.
    pub fn as_slice_with_nul(&self) -> &[libc::c_char] { self.inner.as_slice() }

    /// Similar to the `as_slice` method, but returns a `u8` slice instead of a
    /// `libc::c_char` slice.
    pub fn as_bytes(&self) -> &[u8] {
        unsafe { mem::transmute(self.as_slice()) }
    }

    /// Equivalent to `as_slice_with_nul` except that the type returned is a
    /// `u8` slice instead of a `libc::c_char` slice.
    pub fn as_bytes_with_nul(&self) -> &[u8] {
        unsafe { mem::transmute(self.as_slice_with_nul()) }
    }
}

impl Deref for CString {
    type Target = [libc::c_char];

    fn deref(&self) -> &[libc::c_char] {
        self.inner.slice_to(self.inner.len() - 1)
    }
}

impl fmt::Show for CString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        String::from_utf8_lossy(self.as_bytes()).fmt(f)
    }
}

/// Interpret a C string as a byte slice.
///
/// This function will calculate the length of the C string provided, and it
/// will then return a corresponding slice for the contents of the C string not
/// including the nul terminator.
///
/// This function will tie the lifetime of the returned slice to the lifetime of
/// the pointer provided. This is done to help prevent the slice from escaping
/// the lifetime of the pointer itself. If a longer lifetime is needed, then
/// `mem::copy_lifetime` should be used.
///
/// This function is unsafe because there is no guarantee of the validity of the
/// pointer `raw` or a guarantee that a nul terminator will be found.
///
/// # Example
///
/// ```no_run
/// # extern crate libc;
/// # fn main() {
/// use std::ffi;
/// use std::str;
/// use libc;
///
/// extern {
///     fn my_string() -> *const libc::c_char;
/// }
///
/// unsafe {
///     let to_print = my_string();
///     let slice = ffi::c_str_to_bytes(&to_print);
///     println!("string returned: {}", str::from_utf8(slice).unwrap());
/// }
/// # }
/// ```
pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
    let len = libc::strlen(*raw);
    slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
}

/// Interpret a C string as a byte slice with the nul terminator.
///
/// This function is identical to `from_raw_buf` except that the returned slice
/// will include the nul terminator of the string.
pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
    let len = libc::strlen(*raw) + 1;
    slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
}

#[cfg(test)]
mod tests {
    use prelude::v1::*;
    use super::*;
    use libc;
    use mem;

    #[test]
    fn c_to_rust() {
        let data = b"123\0";
        let ptr = data.as_ptr() as *const libc::c_char;
        unsafe {
            assert_eq!(c_str_to_bytes(&ptr), b"123");
            assert_eq!(c_str_to_bytes_with_nul(&ptr), b"123\0");
        }
    }

    #[test]
    fn simple() {
        let s = CString::from_slice(b"1234");
        assert_eq!(s.as_bytes(), b"1234");
        assert_eq!(s.as_bytes_with_nul(), b"1234\0");
        unsafe {
            assert_eq!(s.as_slice(),
                       mem::transmute::<_, &[libc::c_char]>(b"1234"));
            assert_eq!(s.as_slice_with_nul(),
                       mem::transmute::<_, &[libc::c_char]>(b"1234\0"));
        }
    }

    #[should_fail] #[test]
    fn build_with_zero1() { CString::from_slice(b"\0"); }
    #[should_fail] #[test]
    fn build_with_zero2() { CString::from_vec(vec![0]); }

    #[test]
    fn build_with_zero3() {
        unsafe {
            let s = CString::from_vec_unchecked(vec![0]);
            assert_eq!(s.as_bytes(), b"\0");
        }
    }
}
<commit_msg>Spelling fix compatibel -> compatible<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 fmt;
use iter::IteratorExt;
use libc;
use mem;
use ops::Deref;
use slice::{self, SliceExt, AsSlice};
use string::String;
use vec::Vec;

/// A type representing a C-compatible string
///
/// This type serves the primary purpose of being able to generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
/// A `CString` is created from either a byte slice or a byte vector. After
/// being created, a `CString` predominately inherits all of its methods from
/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
/// `u8` slice can be obtained with the `as_bytes` method.  Slices produced from
/// a `CString` do *not* contain the trailing nul terminator unless otherwise
/// specified.
///
/// # Example
///
/// ```no_run
/// # extern crate libc;
/// # fn main() {
/// use std::ffi::CString;
/// use libc;
///
/// extern {
///     fn my_printer(s: *const libc::c_char);
/// }
///
/// let to_print = "Hello, world!";
/// let c_to_print = CString::from_slice(to_print.as_bytes());
/// unsafe {
///     my_printer(c_to_print.as_ptr());
/// }
/// # }
/// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct CString {
    inner: Vec<libc::c_char>,
}

impl CString {
    /// Create a new C-compatible string from a byte slice.
    ///
    /// This method will copy the data of the slice provided into a new
    /// allocation, ensuring that there is a trailing 0 byte.
    ///
    /// # Panics
    ///
    /// This function will panic if there are any 0 bytes already in the slice
    /// provided.
    pub fn from_slice(v: &[u8]) -> CString {
        CString::from_vec(v.to_vec())
    }

    /// Create a C-compatible string from a byte vector.
    ///
    /// This method will consume ownership of the provided vector, appending a 0
    /// byte to the end after verifying that there are no interior 0 bytes.
    ///
    /// # Panics
    ///
    /// This function will panic if there are any 0 bytes already in the vector
    /// provided.
    pub fn from_vec(v: Vec<u8>) -> CString {
        assert!(!v.iter().any(|&x| x == 0));
        unsafe { CString::from_vec_unchecked(v) }
    }

    /// Create a C-compatible string from a byte vector without checking for
    /// interior 0 bytes.
    ///
    /// This method is equivalent to `from_vec` except that no runtime assertion
    /// is made that `v` contains no 0 bytes.
    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
        v.push(0);
        CString { inner: mem::transmute(v) }
    }

    /// Create a view into this C string which includes the trailing nul
    /// terminator at the end of the string.
    pub fn as_slice_with_nul(&self) -> &[libc::c_char] { self.inner.as_slice() }

    /// Similar to the `as_slice` method, but returns a `u8` slice instead of a
    /// `libc::c_char` slice.
    pub fn as_bytes(&self) -> &[u8] {
        unsafe { mem::transmute(self.as_slice()) }
    }

    /// Equivalent to `as_slice_with_nul` except that the type returned is a
    /// `u8` slice instead of a `libc::c_char` slice.
    pub fn as_bytes_with_nul(&self) -> &[u8] {
        unsafe { mem::transmute(self.as_slice_with_nul()) }
    }
}

impl Deref for CString {
    type Target = [libc::c_char];

    fn deref(&self) -> &[libc::c_char] {
        self.inner.slice_to(self.inner.len() - 1)
    }
}

impl fmt::Show for CString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        String::from_utf8_lossy(self.as_bytes()).fmt(f)
    }
}

/// Interpret a C string as a byte slice.
///
/// This function will calculate the length of the C string provided, and it
/// will then return a corresponding slice for the contents of the C string not
/// including the nul terminator.
///
/// This function will tie the lifetime of the returned slice to the lifetime of
/// the pointer provided. This is done to help prevent the slice from escaping
/// the lifetime of the pointer itself. If a longer lifetime is needed, then
/// `mem::copy_lifetime` should be used.
///
/// This function is unsafe because there is no guarantee of the validity of the
/// pointer `raw` or a guarantee that a nul terminator will be found.
///
/// # Example
///
/// ```no_run
/// # extern crate libc;
/// # fn main() {
/// use std::ffi;
/// use std::str;
/// use libc;
///
/// extern {
///     fn my_string() -> *const libc::c_char;
/// }
///
/// unsafe {
///     let to_print = my_string();
///     let slice = ffi::c_str_to_bytes(&to_print);
///     println!("string returned: {}", str::from_utf8(slice).unwrap());
/// }
/// # }
/// ```
pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
    let len = libc::strlen(*raw);
    slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
}

/// Interpret a C string as a byte slice with the nul terminator.
///
/// This function is identical to `from_raw_buf` except that the returned slice
/// will include the nul terminator of the string.
pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
    let len = libc::strlen(*raw) + 1;
    slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
}

#[cfg(test)]
mod tests {
    use prelude::v1::*;
    use super::*;
    use libc;
    use mem;

    #[test]
    fn c_to_rust() {
        let data = b"123\0";
        let ptr = data.as_ptr() as *const libc::c_char;
        unsafe {
            assert_eq!(c_str_to_bytes(&ptr), b"123");
            assert_eq!(c_str_to_bytes_with_nul(&ptr), b"123\0");
        }
    }

    #[test]
    fn simple() {
        let s = CString::from_slice(b"1234");
        assert_eq!(s.as_bytes(), b"1234");
        assert_eq!(s.as_bytes_with_nul(), b"1234\0");
        unsafe {
            assert_eq!(s.as_slice(),
                       mem::transmute::<_, &[libc::c_char]>(b"1234"));
            assert_eq!(s.as_slice_with_nul(),
                       mem::transmute::<_, &[libc::c_char]>(b"1234\0"));
        }
    }

    #[should_fail] #[test]
    fn build_with_zero1() { CString::from_slice(b"\0"); }
    #[should_fail] #[test]
    fn build_with_zero2() { CString::from_vec(vec![0]); }

    #[test]
    fn build_with_zero3() {
        unsafe {
            let s = CString::from_vec_unchecked(vec![0]);
            assert_eq!(s.as_bytes(), b"\0");
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#[allow(deprecated_mode)];

use json;
use sha1;
use serialize::{Encoder, Encodable, Decoder, Decodable};
use sort;

use core::cmp;
use core::dvec;
use core::either::{Either, Left, Right};
use core::io;
use core::option;
use core::pipes::{recv, oneshot, PortOne, send_one};
use core::prelude::*;
use core::result;
use core::run;
use core::hashmap::linear::LinearMap;
use core::task;
use core::to_bytes;
use core::mutable::Mut;

/**
*
* This is a loose clone of the fbuild build system, made a touch more
* generic (not wired to special cases on files) and much less metaprogram-y
* due to rust's comparative weakness there, relative to python.
*
* It's based around _imperative bulids_ that happen to have some function
* calls cached. That is, it's _just_ a mechanism for describing cached
* functions. This makes it much simpler and smaller than a "build system"
* that produces an IR and evaluates it. The evaluation order is normal
* function calls. Some of them just return really quickly.
*
* A cached function consumes and produces a set of _works_. A work has a
* name, a kind (that determines how the value is to be checked for
* freshness) and a value. Works must also be (de)serializable. Some
* examples of works:
*
*    kind   name    value
*   ------------------------
*    cfg    os      linux
*    file   foo.c   <sha1>
*    url    foo.com <etag>
*
* Works are conceptually single units, but we store them most of the time
* in maps of the form (type,name) => value. These are WorkMaps.
*
* A cached function divides the works it's interested up into inputs and
* outputs, and subdivides those into declared (input) works and
* discovered (input and output) works.
*
* A _declared_ input or is one that is given to the workcache before
* any work actually happens, in the "prep" phase. Even when a function's
* work-doing part (the "exec" phase) never gets called, it has declared
* inputs, which can be checked for freshness (and potentially
* used to determine that the function can be skipped).
*
* The workcache checks _all_ works for freshness, but uses the set of
* discovered outputs from the _previous_ exec (which it will re-discover
* and re-record each time the exec phase runs).
*
* Therefore the discovered works cached in the db might be a
* mis-approximation of the current discoverable works, but this is ok for
* the following reason: we assume that if an artifact A changed from
* depending on B,C,D to depending on B,C,D,E, then A itself changed (as
* part of the change-in-dependencies), so we will be ok.
*
* Each function has a single discriminated output work called its _result_.
* This is only different from other works in that it is returned, by value,
* from a call to the cacheable function; the other output works are used in
* passing to invalidate dependencies elsewhere in the cache, but do not
* otherwise escape from a function invocation. Most functions only have one
* output work anyways.
*
* A database (the central store of a workcache) stores a mappings:
*
* (fn_name,{declared_input}) => ({discovered_input},
*                                {discovered_output},result)
*
* (Note: fbuild, which workcache is based on, has the concept of a declared
* output as separate from a discovered output. This distinction exists only
* as an artifact of how fbuild works: via annotations on function types
* and metaprogramming, with explicit dependency declaration as a fallback.
* Workcache is more explicit about dependencies, and as such treats all
* outputs the same, as discovered-during-the-last-run.)
*
*/

#[deriving_eq]
#[auto_encode]
#[auto_decode]
struct WorkKey {
    kind: ~str,
    name: ~str
}

impl WorkKey: to_bytes::IterBytes {
    #[inline(always)]
    pure fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
        let mut flag = true;
        self.kind.iter_bytes(lsb0, |bytes| {flag = f(bytes); flag});
        if !flag { return; }
        self.name.iter_bytes(lsb0, f);
    }
}

impl WorkKey: cmp::Ord {
    pure fn lt(&self, other: &WorkKey) -> bool {
        self.kind < other.kind ||
            (self.kind == other.kind &&
             self.name < other.name)
    }
    pure fn le(&self, other: &WorkKey) -> bool {
        self.lt(other) || self.eq(other)
    }
    pure fn ge(&self, other: &WorkKey) -> bool {
        self.gt(other) || self.eq(other)
    }
    pure fn gt(&self, other: &WorkKey) -> bool {
        ! self.le(other)
    }
}

impl WorkKey {
    static fn new(kind: &str, name: &str) -> WorkKey {
    WorkKey { kind: kind.to_owned(), name: name.to_owned() }
    }
}

type WorkMap = LinearMap<WorkKey, ~str>;

pub impl<S: Encoder> WorkMap: Encodable<S> {
    fn encode(&self, s: &S) {
        let d = dvec::DVec();
        for self.each |&(k, v)| {
            d.push((copy *k, copy *v))
        }
        let mut v = d.get();
        sort::tim_sort(v);
        v.encode(s)
    }
}

pub impl<D: Decoder> WorkMap: Decodable<D> {
    static fn decode(&self, d: &D) -> WorkMap {
        let v : ~[(WorkKey,~str)] = Decodable::decode(d);
        let mut w = LinearMap::new();
        for v.each |&(k, v)| {
            w.insert(copy k, copy v);
        }
        w
    }
}

struct Database {
    db_filename: Path,
    db_cache: LinearMap<~str, ~str>,
    mut db_dirty: bool
}

impl Database {
    fn prepare(&mut self, fn_name: &str,
               declared_inputs: &WorkMap) -> Option<(WorkMap, WorkMap, ~str)>
    {
        let k = json_encode(&(fn_name, declared_inputs));
        match self.db_cache.find(&k) {
            None => None,
            Some(&v) => Some(json_decode(copy v))
        }
    }

    fn cache(&mut self,
             fn_name: &str,
             declared_inputs: &WorkMap,
             discovered_inputs: &WorkMap,
             discovered_outputs: &WorkMap,
             result: &str) {
        let k = json_encode(&(fn_name, declared_inputs));
        let v = json_encode(&(discovered_inputs,
                              discovered_outputs,
                              result));
        self.db_cache.insert(k,v);
        self.db_dirty = true
    }
}

struct Logger {
    // FIXME #4432: Fill in
    a: ()
}

impl Logger {
    fn info(i: &str) {
        io::println(~"workcache: " + i.to_owned());
    }
}

struct Context {
    db: @Mut<Database>,
    logger: @Mut<Logger>,
    cfg: @json::Object,
    freshness: LinearMap<~str,@fn(&str,&str)->bool>
}

struct Prep {
    ctxt: @Context,
    fn_name: ~str,
    declared_inputs: WorkMap,
}

struct Exec {
    discovered_inputs: WorkMap,
    discovered_outputs: WorkMap
}

struct Work<T> {
    prep: @Mut<Prep>,
    res: Option<Either<T,PortOne<(Exec,T)>>>
}

fn json_encode<T:Encodable<json::Encoder>>(t: &T) -> ~str {
    do io::with_str_writer |wr| {
        t.encode(&json::Encoder(wr));
    }
}

fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
    do io::with_str_reader(s) |rdr| {
        let j = result::unwrap(json::from_reader(rdr));
        Decodable::decode(&json::Decoder(move j))
    }
}

fn digest<T:Encodable<json::Encoder>>(t: &T) -> ~str {
    let mut sha = sha1::sha1();
    sha.input_str(json_encode(t));
    sha.result_str()
}

fn digest_file(path: &Path) -> ~str {
    let mut sha = sha1::sha1();
    let s = io::read_whole_file_str(path);
    sha.input_str(*s.get_ref());
    sha.result_str()
}

impl Context {

    static fn new(db: @Mut<Database>,
                  lg: @Mut<Logger>,
                  cfg: @json::Object) -> Context {
        Context{db: db, logger: lg, cfg: cfg, freshness: LinearMap::new()}
    }

    fn prep<T:Owned
              Encodable<json::Encoder>
              Decodable<json::Decoder>>(
                  @self,
                  fn_name:&str,
                  blk: fn(@Mut<Prep>)->Work<T>) -> Work<T> {
        let p = @Mut(Prep {ctxt: self,
                           fn_name: fn_name.to_owned(),
                           declared_inputs: LinearMap::new()});
        blk(p)
    }
}

trait TPrep {
    fn declare_input(&self, kind:&str, name:&str, val:&str);
    fn is_fresh(&self, cat:&str, kind:&str, name:&str, val:&str) -> bool;
    fn all_fresh(&self, cat:&str, map:&WorkMap) -> bool;
    fn exec<T:Owned
        Encodable<json::Encoder>
        Decodable<json::Decoder>>(&self, blk: ~fn(&Exec) -> T) -> Work<T>;
}

impl @Mut<Prep> : TPrep {
    fn declare_input(&self, kind:&str, name:&str, val:&str) {
        do self.borrow_mut |p| {
            p.declared_inputs.insert(WorkKey::new(kind, name),
                                     val.to_owned());
        }
    }

    fn is_fresh(&self, cat: &str, kind: &str,
                name: &str, val: &str) -> bool {
        do self.borrow_imm |p| {
            let k = kind.to_owned();
            let f = (*p.ctxt.freshness.get(&k))(name, val);
            do p.ctxt.logger.borrow_imm |lg| {
                if f {
                    lg.info(fmt!("%s %s:%s is fresh",
                                 cat, kind, name));
                } else {
                    lg.info(fmt!("%s %s:%s is not fresh",
                                 cat, kind, name))
                }
            }
            f
        }
    }

    fn all_fresh(&self, cat: &str, map: &WorkMap) -> bool {
        for map.each |&(k, v)| {
            if ! self.is_fresh(cat, k.kind, k.name, *v) {
                return false;
            }
        }
        return true;
    }

    fn exec<T:Owned
        Encodable<json::Encoder>
        Decodable<json::Decoder>>(&self,
                                  blk: ~fn(&Exec) -> T) -> Work<T> {

        let mut bo = Some(move blk);

        do self.borrow_imm |p| {
            let cached = do p.ctxt.db.borrow_mut |db| {
                db.prepare(p.fn_name, &p.declared_inputs)
            };

            match move cached {
                Some((ref disc_in, ref disc_out, ref res))
                if self.all_fresh("declared input",
                                  &p.declared_inputs) &&
                self.all_fresh("discovered input", disc_in) &&
                self.all_fresh("discovered output", disc_out) => {
                    Work::new(*self, move Left(json_decode(*res)))
                }

                _ => {
                    let (chan, port) = oneshot::init();
                    let mut blk = None;
                    blk <-> bo;
                    let blk = blk.unwrap();
                    let chan = ~mut Some(move chan);
                    do task::spawn |move blk, move chan| {
                        let exe = Exec{discovered_inputs: LinearMap::new(),
                                       discovered_outputs: LinearMap::new()};
                        let chan = option::swap_unwrap(&mut *chan);
                        let v = blk(&exe);
                        send_one(move chan, (move exe, move v));
                    }

                    Work::new(*self, move Right(move port))
                }
            }
        }
    }
}

impl<T:Owned
       Encodable<json::Encoder>
       Decodable<json::Decoder>>
    Work<T> {
    static fn new(p: @Mut<Prep>, e: Either<T,PortOne<(Exec,T)>>) -> Work<T> {
        move Work { prep: p, res: Some(move e) }
    }
}

// FIXME (#3724): movable self. This should be in impl Work.
fn unwrap<T:Owned
            Encodable<json::Encoder>
            Decodable<json::Decoder>>(w: Work<T>) -> T {

    let mut ww = move w;
    let mut s = None;

    ww.res <-> s;

    match move s {
        None => fail!(),
        Some(Left(move v)) => move v,
        Some(Right(move port)) => {

            let (exe, v) = match recv(move port) {
                oneshot::send(move data) => move data
            };

            let s = json_encode(&v);

            do ww.prep.borrow_imm |p| {
                do p.ctxt.db.borrow_mut |db| {
                    db.cache(p.fn_name,
                             &p.declared_inputs,
                             &exe.discovered_inputs,
                             &exe.discovered_outputs,
                             s);
                }
            }
            move v
        }
    }
}

//#[test]
fn test() {
    use io::WriterUtil;

    let db = @Mut(Database { db_filename: Path("db.json"),
                             db_cache: LinearMap::new(),
                             db_dirty: false });
    let lg = @Mut(Logger { a: () });
    let cfg = @LinearMap::new();
    let cx = @Context::new(db, lg, cfg);
    let w:Work<~str> = do cx.prep("test1") |prep| {
        let pth = Path("foo.c");
        {
            let file = io::file_writer(&pth, [io::Create]).get();
            file.write_str("int main() { return 0; }");
        }

        prep.declare_input("file", pth.to_str(), digest_file(&pth));
        do prep.exec |_exe| {
            let out = Path("foo.o");
            run::run_program("gcc", [~"foo.c", ~"-o", out.to_str()]);
            move out.to_str()
        }
    };
    let s = unwrap(move w);
    io::println(s);
}
<commit_msg>Remove DVec from workcache<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#[allow(deprecated_mode)];

use json;
use sha1;
use serialize::{Encoder, Encodable, Decoder, Decodable};
use sort;

use core::cmp;
use core::either::{Either, Left, Right};
use core::io;
use core::option;
use core::pipes::{recv, oneshot, PortOne, send_one};
use core::prelude::*;
use core::result;
use core::run;
use core::hashmap::linear::LinearMap;
use core::task;
use core::to_bytes;
use core::mutable::Mut;

/**
*
* This is a loose clone of the fbuild build system, made a touch more
* generic (not wired to special cases on files) and much less metaprogram-y
* due to rust's comparative weakness there, relative to python.
*
* It's based around _imperative bulids_ that happen to have some function
* calls cached. That is, it's _just_ a mechanism for describing cached
* functions. This makes it much simpler and smaller than a "build system"
* that produces an IR and evaluates it. The evaluation order is normal
* function calls. Some of them just return really quickly.
*
* A cached function consumes and produces a set of _works_. A work has a
* name, a kind (that determines how the value is to be checked for
* freshness) and a value. Works must also be (de)serializable. Some
* examples of works:
*
*    kind   name    value
*   ------------------------
*    cfg    os      linux
*    file   foo.c   <sha1>
*    url    foo.com <etag>
*
* Works are conceptually single units, but we store them most of the time
* in maps of the form (type,name) => value. These are WorkMaps.
*
* A cached function divides the works it's interested up into inputs and
* outputs, and subdivides those into declared (input) works and
* discovered (input and output) works.
*
* A _declared_ input or is one that is given to the workcache before
* any work actually happens, in the "prep" phase. Even when a function's
* work-doing part (the "exec" phase) never gets called, it has declared
* inputs, which can be checked for freshness (and potentially
* used to determine that the function can be skipped).
*
* The workcache checks _all_ works for freshness, but uses the set of
* discovered outputs from the _previous_ exec (which it will re-discover
* and re-record each time the exec phase runs).
*
* Therefore the discovered works cached in the db might be a
* mis-approximation of the current discoverable works, but this is ok for
* the following reason: we assume that if an artifact A changed from
* depending on B,C,D to depending on B,C,D,E, then A itself changed (as
* part of the change-in-dependencies), so we will be ok.
*
* Each function has a single discriminated output work called its _result_.
* This is only different from other works in that it is returned, by value,
* from a call to the cacheable function; the other output works are used in
* passing to invalidate dependencies elsewhere in the cache, but do not
* otherwise escape from a function invocation. Most functions only have one
* output work anyways.
*
* A database (the central store of a workcache) stores a mappings:
*
* (fn_name,{declared_input}) => ({discovered_input},
*                                {discovered_output},result)
*
* (Note: fbuild, which workcache is based on, has the concept of a declared
* output as separate from a discovered output. This distinction exists only
* as an artifact of how fbuild works: via annotations on function types
* and metaprogramming, with explicit dependency declaration as a fallback.
* Workcache is more explicit about dependencies, and as such treats all
* outputs the same, as discovered-during-the-last-run.)
*
*/

#[deriving_eq]
#[auto_encode]
#[auto_decode]
struct WorkKey {
    kind: ~str,
    name: ~str
}

impl WorkKey: to_bytes::IterBytes {
    #[inline(always)]
    pure fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
        let mut flag = true;
        self.kind.iter_bytes(lsb0, |bytes| {flag = f(bytes); flag});
        if !flag { return; }
        self.name.iter_bytes(lsb0, f);
    }
}

impl WorkKey: cmp::Ord {
    pure fn lt(&self, other: &WorkKey) -> bool {
        self.kind < other.kind ||
            (self.kind == other.kind &&
             self.name < other.name)
    }
    pure fn le(&self, other: &WorkKey) -> bool {
        self.lt(other) || self.eq(other)
    }
    pure fn ge(&self, other: &WorkKey) -> bool {
        self.gt(other) || self.eq(other)
    }
    pure fn gt(&self, other: &WorkKey) -> bool {
        ! self.le(other)
    }
}

impl WorkKey {
    static fn new(kind: &str, name: &str) -> WorkKey {
    WorkKey { kind: kind.to_owned(), name: name.to_owned() }
    }
}

type WorkMap = LinearMap<WorkKey, ~str>;

pub impl<S: Encoder> WorkMap: Encodable<S> {
    fn encode(&self, s: &S) {
        let mut d = ~[];
        for self.each |&(k, v)| {
            d.push((copy *k, copy *v))
        }
        sort::tim_sort(d);
        d.encode(s)
    }
}

pub impl<D: Decoder> WorkMap: Decodable<D> {
    static fn decode(&self, d: &D) -> WorkMap {
        let v : ~[(WorkKey,~str)] = Decodable::decode(d);
        let mut w = LinearMap::new();
        for v.each |&(k, v)| {
            w.insert(copy k, copy v);
        }
        w
    }
}

struct Database {
    db_filename: Path,
    db_cache: LinearMap<~str, ~str>,
    mut db_dirty: bool
}

impl Database {
    fn prepare(&mut self, fn_name: &str,
               declared_inputs: &WorkMap) -> Option<(WorkMap, WorkMap, ~str)>
    {
        let k = json_encode(&(fn_name, declared_inputs));
        match self.db_cache.find(&k) {
            None => None,
            Some(&v) => Some(json_decode(copy v))
        }
    }

    fn cache(&mut self,
             fn_name: &str,
             declared_inputs: &WorkMap,
             discovered_inputs: &WorkMap,
             discovered_outputs: &WorkMap,
             result: &str) {
        let k = json_encode(&(fn_name, declared_inputs));
        let v = json_encode(&(discovered_inputs,
                              discovered_outputs,
                              result));
        self.db_cache.insert(k,v);
        self.db_dirty = true
    }
}

struct Logger {
    // FIXME #4432: Fill in
    a: ()
}

impl Logger {
    fn info(i: &str) {
        io::println(~"workcache: " + i.to_owned());
    }
}

struct Context {
    db: @Mut<Database>,
    logger: @Mut<Logger>,
    cfg: @json::Object,
    freshness: LinearMap<~str,@fn(&str,&str)->bool>
}

struct Prep {
    ctxt: @Context,
    fn_name: ~str,
    declared_inputs: WorkMap,
}

struct Exec {
    discovered_inputs: WorkMap,
    discovered_outputs: WorkMap
}

struct Work<T> {
    prep: @Mut<Prep>,
    res: Option<Either<T,PortOne<(Exec,T)>>>
}

fn json_encode<T:Encodable<json::Encoder>>(t: &T) -> ~str {
    do io::with_str_writer |wr| {
        t.encode(&json::Encoder(wr));
    }
}

fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
    do io::with_str_reader(s) |rdr| {
        let j = result::unwrap(json::from_reader(rdr));
        Decodable::decode(&json::Decoder(move j))
    }
}

fn digest<T:Encodable<json::Encoder>>(t: &T) -> ~str {
    let mut sha = sha1::sha1();
    sha.input_str(json_encode(t));
    sha.result_str()
}

fn digest_file(path: &Path) -> ~str {
    let mut sha = sha1::sha1();
    let s = io::read_whole_file_str(path);
    sha.input_str(*s.get_ref());
    sha.result_str()
}

impl Context {

    static fn new(db: @Mut<Database>,
                  lg: @Mut<Logger>,
                  cfg: @json::Object) -> Context {
        Context{db: db, logger: lg, cfg: cfg, freshness: LinearMap::new()}
    }

    fn prep<T:Owned
              Encodable<json::Encoder>
              Decodable<json::Decoder>>(
                  @self,
                  fn_name:&str,
                  blk: fn(@Mut<Prep>)->Work<T>) -> Work<T> {
        let p = @Mut(Prep {ctxt: self,
                           fn_name: fn_name.to_owned(),
                           declared_inputs: LinearMap::new()});
        blk(p)
    }
}

trait TPrep {
    fn declare_input(&self, kind:&str, name:&str, val:&str);
    fn is_fresh(&self, cat:&str, kind:&str, name:&str, val:&str) -> bool;
    fn all_fresh(&self, cat:&str, map:&WorkMap) -> bool;
    fn exec<T:Owned
        Encodable<json::Encoder>
        Decodable<json::Decoder>>(&self, blk: ~fn(&Exec) -> T) -> Work<T>;
}

impl @Mut<Prep> : TPrep {
    fn declare_input(&self, kind:&str, name:&str, val:&str) {
        do self.borrow_mut |p| {
            p.declared_inputs.insert(WorkKey::new(kind, name),
                                     val.to_owned());
        }
    }

    fn is_fresh(&self, cat: &str, kind: &str,
                name: &str, val: &str) -> bool {
        do self.borrow_imm |p| {
            let k = kind.to_owned();
            let f = (*p.ctxt.freshness.get(&k))(name, val);
            do p.ctxt.logger.borrow_imm |lg| {
                if f {
                    lg.info(fmt!("%s %s:%s is fresh",
                                 cat, kind, name));
                } else {
                    lg.info(fmt!("%s %s:%s is not fresh",
                                 cat, kind, name))
                }
            }
            f
        }
    }

    fn all_fresh(&self, cat: &str, map: &WorkMap) -> bool {
        for map.each |&(k, v)| {
            if ! self.is_fresh(cat, k.kind, k.name, *v) {
                return false;
            }
        }
        return true;
    }

    fn exec<T:Owned
        Encodable<json::Encoder>
        Decodable<json::Decoder>>(&self,
                                  blk: ~fn(&Exec) -> T) -> Work<T> {

        let mut bo = Some(move blk);

        do self.borrow_imm |p| {
            let cached = do p.ctxt.db.borrow_mut |db| {
                db.prepare(p.fn_name, &p.declared_inputs)
            };

            match move cached {
                Some((ref disc_in, ref disc_out, ref res))
                if self.all_fresh("declared input",
                                  &p.declared_inputs) &&
                self.all_fresh("discovered input", disc_in) &&
                self.all_fresh("discovered output", disc_out) => {
                    Work::new(*self, move Left(json_decode(*res)))
                }

                _ => {
                    let (chan, port) = oneshot::init();
                    let mut blk = None;
                    blk <-> bo;
                    let blk = blk.unwrap();
                    let chan = ~mut Some(move chan);
                    do task::spawn |move blk, move chan| {
                        let exe = Exec{discovered_inputs: LinearMap::new(),
                                       discovered_outputs: LinearMap::new()};
                        let chan = option::swap_unwrap(&mut *chan);
                        let v = blk(&exe);
                        send_one(move chan, (move exe, move v));
                    }

                    Work::new(*self, move Right(move port))
                }
            }
        }
    }
}

impl<T:Owned
       Encodable<json::Encoder>
       Decodable<json::Decoder>>
    Work<T> {
    static fn new(p: @Mut<Prep>, e: Either<T,PortOne<(Exec,T)>>) -> Work<T> {
        move Work { prep: p, res: Some(move e) }
    }
}

// FIXME (#3724): movable self. This should be in impl Work.
fn unwrap<T:Owned
            Encodable<json::Encoder>
            Decodable<json::Decoder>>(w: Work<T>) -> T {

    let mut ww = move w;
    let mut s = None;

    ww.res <-> s;

    match move s {
        None => fail!(),
        Some(Left(move v)) => move v,
        Some(Right(move port)) => {

            let (exe, v) = match recv(move port) {
                oneshot::send(move data) => move data
            };

            let s = json_encode(&v);

            do ww.prep.borrow_imm |p| {
                do p.ctxt.db.borrow_mut |db| {
                    db.cache(p.fn_name,
                             &p.declared_inputs,
                             &exe.discovered_inputs,
                             &exe.discovered_outputs,
                             s);
                }
            }
            move v
        }
    }
}

//#[test]
fn test() {
    use io::WriterUtil;

    let db = @Mut(Database { db_filename: Path("db.json"),
                             db_cache: LinearMap::new(),
                             db_dirty: false });
    let lg = @Mut(Logger { a: () });
    let cfg = @LinearMap::new();
    let cx = @Context::new(db, lg, cfg);
    let w:Work<~str> = do cx.prep("test1") |prep| {
        let pth = Path("foo.c");
        {
            let file = io::file_writer(&pth, [io::Create]).get();
            file.write_str("int main() { return 0; }");
        }

        prep.declare_input("file", pth.to_str(), digest_file(&pth));
        do prep.exec |_exe| {
            let out = Path("foo.o");
            run::run_program("gcc", [~"foo.c", ~"-o", out.to_str()]);
            move out.to_str()
        }
    };
    let s = unwrap(move w);
    io::println(s);
}
<|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 attr::AttrMetaMethods;
use diagnostic::SpanHandler;
use fold::Folder;
use {ast, fold, attr};
use codemap::Spanned;
use ptr::P;

/// A folder that strips out items that do not belong in the current
/// configuration.
struct Context<'a> {
    in_cfg: |attrs: &[ast::Attribute]|: 'a -> bool,
}

// Support conditional compilation by transforming the AST, stripping out
// any items that do not belong in the current configuration
pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate {
    let config = krate.config.clone();
    strip_items(krate, |attrs| in_cfg(diagnostic, config.as_slice(), attrs))
}

impl<'a> fold::Folder for Context<'a> {
    fn fold_mod(&mut self, module: ast::Mod) -> ast::Mod {
        fold_mod(self, module)
    }
    fn fold_block(&mut self, block: P<ast::Block>) -> P<ast::Block> {
        fold_block(self, block)
    }
    fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod {
        fold_foreign_mod(self, foreign_mod)
    }
    fn fold_item_underscore(&mut self, item: ast::Item_) -> ast::Item_ {
        fold_item_underscore(self, item)
    }
    fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
        fold_expr(self, expr)
    }
    fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
        fold::noop_fold_mac(mac, self)
    }
}

pub fn strip_items(krate: ast::Crate,
                   in_cfg: |attrs: &[ast::Attribute]| -> bool)
                   -> ast::Crate {
    let mut ctxt = Context {
        in_cfg: in_cfg,
    };
    ctxt.fold_crate(krate)
}

fn filter_view_item(cx: &mut Context, view_item: ast::ViewItem) -> Option<ast::ViewItem> {
    if view_item_in_cfg(cx, &view_item) {
        Some(view_item)
    } else {
        None
    }
}

fn fold_mod(cx: &mut Context, ast::Mod {inner, view_items, items}: ast::Mod) -> ast::Mod {
    ast::Mod {
        inner: inner,
        view_items: view_items.into_iter().filter_map(|a| {
            filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
        }).collect(),
        items: items.into_iter().filter_map(|a| {
            if item_in_cfg(cx, &*a) {
                Some(cx.fold_item(a))
            } else {
                None
            }
        }).flat_map(|x| x.into_iter()).collect()
    }
}

fn filter_foreign_item(cx: &mut Context, item: P<ast::ForeignItem>)
                       -> Option<P<ast::ForeignItem>> {
    if foreign_item_in_cfg(cx, &*item) {
        Some(item)
    } else {
        None
    }
}

fn fold_foreign_mod(cx: &mut Context, ast::ForeignMod {abi, view_items, items}: ast::ForeignMod)
                    -> ast::ForeignMod {
    ast::ForeignMod {
        abi: abi,
        view_items: view_items.into_iter().filter_map(|a| {
            filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
        }).collect(),
        items: items.into_iter()
                    .filter_map(|a| filter_foreign_item(cx, a))
                    .collect()
    }
}

fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ {
    let item = match item {
        ast::ItemImpl(a, b, c, impl_items) => {
            let impl_items = impl_items.into_iter()
                                       .filter(|ii| impl_item_in_cfg(cx, ii))
                                       .collect();
            ast::ItemImpl(a, b, c, impl_items)
        }
        ast::ItemTrait(a, b, c, methods) => {
            let methods = methods.into_iter()
                                 .filter(|m| trait_method_in_cfg(cx, m))
                                 .collect();
            ast::ItemTrait(a, b, c, methods)
        }
        ast::ItemStruct(def, generics) => {
            ast::ItemStruct(fold_struct(cx, def), generics)
        }
        ast::ItemEnum(def, generics) => {
            let mut variants = def.variants.into_iter().filter_map(|v| {
                if !(cx.in_cfg)(v.node.attrs.as_slice()) {
                    None
                } else {
                    Some(v.map(|Spanned {node: ast::Variant_ {id, name, attrs, kind,
                                                              disr_expr, vis}, span}| {
                        Spanned {
                            node: ast::Variant_ {
                                id: id,
                                name: name,
                                attrs: attrs,
                                kind: match kind {
                                    ast::TupleVariantKind(..) => kind,
                                    ast::StructVariantKind(def) => {
                                        ast::StructVariantKind(fold_struct(cx, def))
                                    }
                                },
                                disr_expr: disr_expr,
                                vis: vis
                            },
                            span: span
                        }
                    }))
                }
            });
            ast::ItemEnum(ast::EnumDef {
                variants: variants.collect(),
            }, generics)
        }
        item => item,
    };

    fold::noop_fold_item_underscore(item, cx)
}

fn fold_struct(cx: &mut Context, def: P<ast::StructDef>) -> P<ast::StructDef> {
    def.map(|ast::StructDef { fields, ctor_id }| {
        ast::StructDef {
            fields: fields.into_iter().filter(|m| {
                (cx.in_cfg)(m.node.attrs.as_slice())
            }).collect(),
            ctor_id: ctor_id,
        }
    })
}

fn retain_stmt(cx: &mut Context, stmt: &ast::Stmt) -> bool {
    match stmt.node {
        ast::StmtDecl(ref decl, _) => {
            match decl.node {
                ast::DeclItem(ref item) => {
                    item_in_cfg(cx, &**item)
                }
                _ => true
            }
        }
        _ => true
    }
}

fn fold_block(cx: &mut Context, b: P<ast::Block>) -> P<ast::Block> {
    b.map(|ast::Block {id, view_items, stmts, expr, rules, span}| {
        let resulting_stmts: Vec<P<ast::Stmt>> =
            stmts.into_iter().filter(|a| retain_stmt(cx, &**a)).collect();
        let resulting_stmts = resulting_stmts.into_iter()
            .flat_map(|stmt| cx.fold_stmt(stmt).into_iter())
            .collect();
        let filtered_view_items = view_items.into_iter().filter_map(|a| {
            filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
        }).collect();
        ast::Block {
            id: id,
            view_items: filtered_view_items,
            stmts: resulting_stmts,
            expr: expr.map(|x| cx.fold_expr(x)),
            rules: rules,
            span: span,
        }
    })
}

fn fold_expr(cx: &mut Context, expr: P<ast::Expr>) -> P<ast::Expr> {
    expr.map(|ast::Expr {id, span, node}| {
        fold::noop_fold_expr(ast::Expr {
            id: id,
            node: match node {
                ast::ExprMatch(m, arms, source) => {
                    ast::ExprMatch(m, arms.into_iter()
                                        .filter(|a| (cx.in_cfg)(a.attrs.as_slice()))
                                        .collect(), source)
                }
                _ => node
            },
            span: span
        }, cx)
    })
}

fn item_in_cfg(cx: &mut Context, item: &ast::Item) -> bool {
    return (cx.in_cfg)(item.attrs.as_slice());
}

fn foreign_item_in_cfg(cx: &mut Context, item: &ast::ForeignItem) -> bool {
    return (cx.in_cfg)(item.attrs.as_slice());
}

fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool {
    return (cx.in_cfg)(item.attrs.as_slice());
}

fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool {
    match *meth {
        ast::RequiredMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
        ast::ProvidedMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
        ast::TypeTraitItem(ref typ) => (cx.in_cfg)(typ.attrs.as_slice()),
    }
}

fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool {
    match *impl_item {
        ast::MethodImplItem(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
        ast::TypeImplItem(ref typ) => (cx.in_cfg)(typ.attrs.as_slice()),
    }
}

// Determine if an item should be translated in the current crate
// configuration based on the item's attributes
fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attribute]) -> bool {
    let mut in_cfg = false;
    let mut seen_cfg = false;
    for attr in attrs.iter() {
        let mis = match attr.node.value.node {
            ast::MetaList(_, ref mis) if attr.check_name("cfg") => mis,
            _ => continue
        };

        if mis.len() != 1 {
            diagnostic.span_err(attr.span, "expected 1 cfg-pattern");
            return false;
        }

        if seen_cfg {
            diagnostic.span_err(attr.span, "The semantics of multiple `#[cfg(..)]` attributes on \
                                            same item are changing from the union of the cfgs to \
                                            the intersection of the cfgs. Change `#[cfg(a)] \
                                            #[cfg(b)]` to `#[cfg(any(a, b))]`.");
            return false;
        }

        seen_cfg = true;
        in_cfg |= attr::cfg_matches(diagnostic, cfg, &*mis[0]);
    }
    in_cfg | !seen_cfg
}

<commit_msg>Finish cfg syntax transition<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 attr::AttrMetaMethods;
use diagnostic::SpanHandler;
use fold::Folder;
use {ast, fold, attr};
use codemap::Spanned;
use ptr::P;

/// A folder that strips out items that do not belong in the current
/// configuration.
struct Context<'a> {
    in_cfg: |attrs: &[ast::Attribute]|: 'a -> bool,
}

// Support conditional compilation by transforming the AST, stripping out
// any items that do not belong in the current configuration
pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate {
    let config = krate.config.clone();
    strip_items(krate, |attrs| in_cfg(diagnostic, config.as_slice(), attrs))
}

impl<'a> fold::Folder for Context<'a> {
    fn fold_mod(&mut self, module: ast::Mod) -> ast::Mod {
        fold_mod(self, module)
    }
    fn fold_block(&mut self, block: P<ast::Block>) -> P<ast::Block> {
        fold_block(self, block)
    }
    fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod {
        fold_foreign_mod(self, foreign_mod)
    }
    fn fold_item_underscore(&mut self, item: ast::Item_) -> ast::Item_ {
        fold_item_underscore(self, item)
    }
    fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
        fold_expr(self, expr)
    }
    fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
        fold::noop_fold_mac(mac, self)
    }
}

pub fn strip_items(krate: ast::Crate,
                   in_cfg: |attrs: &[ast::Attribute]| -> bool)
                   -> ast::Crate {
    let mut ctxt = Context {
        in_cfg: in_cfg,
    };
    ctxt.fold_crate(krate)
}

fn filter_view_item(cx: &mut Context, view_item: ast::ViewItem) -> Option<ast::ViewItem> {
    if view_item_in_cfg(cx, &view_item) {
        Some(view_item)
    } else {
        None
    }
}

fn fold_mod(cx: &mut Context, ast::Mod {inner, view_items, items}: ast::Mod) -> ast::Mod {
    ast::Mod {
        inner: inner,
        view_items: view_items.into_iter().filter_map(|a| {
            filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
        }).collect(),
        items: items.into_iter().filter_map(|a| {
            if item_in_cfg(cx, &*a) {
                Some(cx.fold_item(a))
            } else {
                None
            }
        }).flat_map(|x| x.into_iter()).collect()
    }
}

fn filter_foreign_item(cx: &mut Context, item: P<ast::ForeignItem>)
                       -> Option<P<ast::ForeignItem>> {
    if foreign_item_in_cfg(cx, &*item) {
        Some(item)
    } else {
        None
    }
}

fn fold_foreign_mod(cx: &mut Context, ast::ForeignMod {abi, view_items, items}: ast::ForeignMod)
                    -> ast::ForeignMod {
    ast::ForeignMod {
        abi: abi,
        view_items: view_items.into_iter().filter_map(|a| {
            filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
        }).collect(),
        items: items.into_iter()
                    .filter_map(|a| filter_foreign_item(cx, a))
                    .collect()
    }
}

fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ {
    let item = match item {
        ast::ItemImpl(a, b, c, impl_items) => {
            let impl_items = impl_items.into_iter()
                                       .filter(|ii| impl_item_in_cfg(cx, ii))
                                       .collect();
            ast::ItemImpl(a, b, c, impl_items)
        }
        ast::ItemTrait(a, b, c, methods) => {
            let methods = methods.into_iter()
                                 .filter(|m| trait_method_in_cfg(cx, m))
                                 .collect();
            ast::ItemTrait(a, b, c, methods)
        }
        ast::ItemStruct(def, generics) => {
            ast::ItemStruct(fold_struct(cx, def), generics)
        }
        ast::ItemEnum(def, generics) => {
            let mut variants = def.variants.into_iter().filter_map(|v| {
                if !(cx.in_cfg)(v.node.attrs.as_slice()) {
                    None
                } else {
                    Some(v.map(|Spanned {node: ast::Variant_ {id, name, attrs, kind,
                                                              disr_expr, vis}, span}| {
                        Spanned {
                            node: ast::Variant_ {
                                id: id,
                                name: name,
                                attrs: attrs,
                                kind: match kind {
                                    ast::TupleVariantKind(..) => kind,
                                    ast::StructVariantKind(def) => {
                                        ast::StructVariantKind(fold_struct(cx, def))
                                    }
                                },
                                disr_expr: disr_expr,
                                vis: vis
                            },
                            span: span
                        }
                    }))
                }
            });
            ast::ItemEnum(ast::EnumDef {
                variants: variants.collect(),
            }, generics)
        }
        item => item,
    };

    fold::noop_fold_item_underscore(item, cx)
}

fn fold_struct(cx: &mut Context, def: P<ast::StructDef>) -> P<ast::StructDef> {
    def.map(|ast::StructDef { fields, ctor_id }| {
        ast::StructDef {
            fields: fields.into_iter().filter(|m| {
                (cx.in_cfg)(m.node.attrs.as_slice())
            }).collect(),
            ctor_id: ctor_id,
        }
    })
}

fn retain_stmt(cx: &mut Context, stmt: &ast::Stmt) -> bool {
    match stmt.node {
        ast::StmtDecl(ref decl, _) => {
            match decl.node {
                ast::DeclItem(ref item) => {
                    item_in_cfg(cx, &**item)
                }
                _ => true
            }
        }
        _ => true
    }
}

fn fold_block(cx: &mut Context, b: P<ast::Block>) -> P<ast::Block> {
    b.map(|ast::Block {id, view_items, stmts, expr, rules, span}| {
        let resulting_stmts: Vec<P<ast::Stmt>> =
            stmts.into_iter().filter(|a| retain_stmt(cx, &**a)).collect();
        let resulting_stmts = resulting_stmts.into_iter()
            .flat_map(|stmt| cx.fold_stmt(stmt).into_iter())
            .collect();
        let filtered_view_items = view_items.into_iter().filter_map(|a| {
            filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
        }).collect();
        ast::Block {
            id: id,
            view_items: filtered_view_items,
            stmts: resulting_stmts,
            expr: expr.map(|x| cx.fold_expr(x)),
            rules: rules,
            span: span,
        }
    })
}

fn fold_expr(cx: &mut Context, expr: P<ast::Expr>) -> P<ast::Expr> {
    expr.map(|ast::Expr {id, span, node}| {
        fold::noop_fold_expr(ast::Expr {
            id: id,
            node: match node {
                ast::ExprMatch(m, arms, source) => {
                    ast::ExprMatch(m, arms.into_iter()
                                        .filter(|a| (cx.in_cfg)(a.attrs.as_slice()))
                                        .collect(), source)
                }
                _ => node
            },
            span: span
        }, cx)
    })
}

fn item_in_cfg(cx: &mut Context, item: &ast::Item) -> bool {
    return (cx.in_cfg)(item.attrs.as_slice());
}

fn foreign_item_in_cfg(cx: &mut Context, item: &ast::ForeignItem) -> bool {
    return (cx.in_cfg)(item.attrs.as_slice());
}

fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool {
    return (cx.in_cfg)(item.attrs.as_slice());
}

fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool {
    match *meth {
        ast::RequiredMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
        ast::ProvidedMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
        ast::TypeTraitItem(ref typ) => (cx.in_cfg)(typ.attrs.as_slice()),
    }
}

fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool {
    match *impl_item {
        ast::MethodImplItem(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
        ast::TypeImplItem(ref typ) => (cx.in_cfg)(typ.attrs.as_slice()),
    }
}

// Determine if an item should be translated in the current crate
// configuration based on the item's attributes
fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attribute]) -> bool {
    attrs.iter().all(|attr| {
        let mis = match attr.node.value.node {
            ast::MetaList(_, ref mis) if attr.check_name("cfg") => mis,
            _ => return true
        };

        if mis.len() != 1 {
            diagnostic.span_err(attr.span, "expected 1 cfg-pattern");
            return true;
        }

        attr::cfg_matches(diagnostic, cfg, &*mis[0])
    })
}

<|endoftext|>


<commit_before><commit_msg> removed filter for testing<commit_after><|endoftext|>


<commit_before><commit_msg>an empy message<commit_after><|endoftext|>


<commit_before>/*

Idea: provide functions for 'exhaustive' and 'random' modification of vecs.

  two functions, "return all edits" and "return a random edit" <-- leaning toward this model
    or
  two functions, "return the number of possible edits" and "return edit #n"

It would be nice if this could be data-driven, so the two functions could share information:
  type vec_modifier = rec(fn (&<T> v, uint i) -> [T] fun, uint lo, uint di);
  const [vec_modifier] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...];
But that gives me "error: internal compiler error unimplemented consts that's not a plain literal".
https://github.com/graydon/rust/issues/570

vec_edits is not an iter because iters might go away and:
https://github.com/graydon/rust/issues/639

vec_omit and friends are not type-parameterized because:
https://github.com/graydon/rust/issues/640

*/

use std;
import std::vec;
import std::vec::slice;
import std::vec::len;
import std::int;

//fn vec_reverse(&<T> v) -> [T] { ... }

fn vec_omit<@T>(v: &[T], i: uint) -> [T] {
    slice(v, 0u, i) + slice(v, i + 1u, len(v))
}
fn vec_dup<@T>(v: &[T], i: uint) -> [T] {
    slice(v, 0u, i) + [v[i]] + slice(v, i, len(v))
}
fn vec_swadj<@T>(v: &[T], i: uint) -> [T] {
    slice(v, 0u, i) + [v[i + 1u], v[i]] + slice(v, i + 2u, len(v))
}
fn vec_prefix<@T>(v: &[T], i: uint) -> [T] { slice(v, 0u, i) }
fn vec_suffix<@T>(v: &[T], i: uint) -> [T] { slice(v, i, len(v)) }

fn vec_poke<@T>(v: &[T], i: uint, x: &T) -> [T] {
    slice(v, 0u, i) + [x] + slice(v, i + 1u, len(v))
}
fn vec_insert<@T>(v: &[T], i: uint, x: &T) -> [T] {
    slice(v, 0u, i) + [x] + slice(v, i, len(v))
}

// Iterates over 0...length, skipping the specified number on each side.
iter ix(skip_low: uint, skip_high: uint, length: uint) -> uint {
    let i: uint = skip_low;
    while i + skip_high <= length { put i; i += 1u; }
}

// Returns a bunch of modified versions of v, some of which introduce new elements (borrowed from xs).
fn vec_edits<@T>(v: &[T], xs: &[T]) -> [[T]] {
    let edits: [[T]] = [];
    let Lv: uint = len(v);

    if Lv != 1u {
        edits +=
            [[]]; // When Lv == 1u, this is redundant with omit
                  //if (Lv >= 3u) { edits += ~[vec_reverse(v)]; }

    }
    for each i: uint in ix(0u, 1u, Lv) { edits += [vec_omit(v, i)]; }
    for each i: uint in ix(0u, 1u, Lv) { edits += [vec_dup(v, i)]; }
    for each i: uint in ix(0u, 2u, Lv) { edits += [vec_swadj(v, i)]; }
    for each i: uint in ix(1u, 2u, Lv) { edits += [vec_prefix(v, i)]; }
    for each i: uint in ix(2u, 1u, Lv) { edits += [vec_suffix(v, i)]; }

    for each j: uint in ix(0u, 1u, len(xs)) {
        for each i: uint in ix(0u, 1u, Lv) {
            edits += [vec_poke(v, i, xs[j])];
        }
        for each i: uint in ix(0u, 0u, Lv) {
            edits += [vec_insert(v, i, xs[j])];
        }
    }

    edits
}

// Would be nice if this were built in: https://github.com/graydon/rust/issues/424
fn vec_to_str(v: &[int]) -> str {
    let i = 0u;
    let s = "[";
    while i < len(v) {
        s += int::str(v[i]);
        if i + 1u < len(v) { s += ", " }
        i += 1u;
    }
    ret s + "]";
}

fn show_edits(a: &[int], xs: &[int]) {
    log_err "=== Edits of " + vec_to_str(a) + " ===";
    let b = vec_edits(a, xs);
    for each i: uint in ix(0u, 1u, len(b)) { log_err vec_to_str(b[i]); }
}

fn demo_edits() {
    let xs = [7, 8];
    show_edits([], xs);
    show_edits([1], xs);
    show_edits([1, 2], xs);
    show_edits([1, 2, 3], xs);
    show_edits([1, 2, 3, 4], xs);
}

fn main() { demo_edits(); }
<commit_msg>ivec_fuzz: remove obsolete comments<commit_after>/*

Idea: provide functions for 'exhaustive' and 'random' modification of vecs.

  two functions, "return all edits" and "return a random edit" <-- leaning toward this model
    or
  two functions, "return the number of possible edits" and "return edit #n"

It would be nice if this could be data-driven, so the two functions could share information:
  type vec_modifier = rec(fn (&<T> v, uint i) -> [T] fun, uint lo, uint di);
  const [vec_modifier] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...];
But that gives me "error: internal compiler error unimplemented consts that's not a plain literal".
https://github.com/graydon/rust/issues/570

vec_edits is not an iter because iters might go away.

*/

use std;
import std::vec;
import std::vec::slice;
import std::vec::len;
import std::int;

//fn vec_reverse(&<T> v) -> [T] { ... }

fn vec_omit<@T>(v: &[T], i: uint) -> [T] {
    slice(v, 0u, i) + slice(v, i + 1u, len(v))
}
fn vec_dup<@T>(v: &[T], i: uint) -> [T] {
    slice(v, 0u, i) + [v[i]] + slice(v, i, len(v))
}
fn vec_swadj<@T>(v: &[T], i: uint) -> [T] {
    slice(v, 0u, i) + [v[i + 1u], v[i]] + slice(v, i + 2u, len(v))
}
fn vec_prefix<@T>(v: &[T], i: uint) -> [T] { slice(v, 0u, i) }
fn vec_suffix<@T>(v: &[T], i: uint) -> [T] { slice(v, i, len(v)) }

fn vec_poke<@T>(v: &[T], i: uint, x: &T) -> [T] {
    slice(v, 0u, i) + [x] + slice(v, i + 1u, len(v))
}
fn vec_insert<@T>(v: &[T], i: uint, x: &T) -> [T] {
    slice(v, 0u, i) + [x] + slice(v, i, len(v))
}

// Iterates over 0...length, skipping the specified number on each side.
iter ix(skip_low: uint, skip_high: uint, length: uint) -> uint {
    let i: uint = skip_low;
    while i + skip_high <= length { put i; i += 1u; }
}

// Returns a bunch of modified versions of v, some of which introduce new elements (borrowed from xs).
fn vec_edits<@T>(v: &[T], xs: &[T]) -> [[T]] {
    let edits: [[T]] = [];
    let Lv: uint = len(v);

    if Lv != 1u {
        edits +=
            [[]]; // When Lv == 1u, this is redundant with omit
                  //if (Lv >= 3u) { edits += ~[vec_reverse(v)]; }

    }
    for each i: uint in ix(0u, 1u, Lv) { edits += [vec_omit(v, i)]; }
    for each i: uint in ix(0u, 1u, Lv) { edits += [vec_dup(v, i)]; }
    for each i: uint in ix(0u, 2u, Lv) { edits += [vec_swadj(v, i)]; }
    for each i: uint in ix(1u, 2u, Lv) { edits += [vec_prefix(v, i)]; }
    for each i: uint in ix(2u, 1u, Lv) { edits += [vec_suffix(v, i)]; }

    for each j: uint in ix(0u, 1u, len(xs)) {
        for each i: uint in ix(0u, 1u, Lv) {
            edits += [vec_poke(v, i, xs[j])];
        }
        for each i: uint in ix(0u, 0u, Lv) {
            edits += [vec_insert(v, i, xs[j])];
        }
    }

    edits
}

// Would be nice if this were built in: https://github.com/graydon/rust/issues/424
fn vec_to_str(v: &[int]) -> str {
    let i = 0u;
    let s = "[";
    while i < len(v) {
        s += int::str(v[i]);
        if i + 1u < len(v) { s += ", " }
        i += 1u;
    }
    ret s + "]";
}

fn show_edits(a: &[int], xs: &[int]) {
    log_err "=== Edits of " + vec_to_str(a) + " ===";
    let b = vec_edits(a, xs);
    for each i: uint in ix(0u, 1u, len(b)) { log_err vec_to_str(b[i]); }
}

fn demo_edits() {
    let xs = [7, 8];
    show_edits([], xs);
    show_edits([1], xs);
    show_edits([1, 2], xs);
    show_edits([1, 2, 3], xs);
    show_edits([1, 2, 3, 4], xs);
}

fn main() { demo_edits(); }
<|endoftext|>


<commit_before><commit_msg>call os command<commit_after><|endoftext|>


<commit_before><commit_msg>Added gaussian mutation operator<commit_after>/// Performs gaussian mutation on solution parameters
///
/// Performs gaussian mutation on real-valued solution parameters,
/// currently hard-coded for 30 problem variables for the ZDT1
/// synthetic test function.
extern crate rand;
use rand::{random, thread_rng, Rng};

// bounds hard-coded for ZDT1 i.e. (0,1)
pub fn gaussian_mutation(mut parameters: [f32; 30], mutation_rate: f32) -> [f32; 30] {
    let std = 1_f32 - 0_f32 / 10_f32;
    for parameter in &mut parameters[..] {
        if random::<f32>() <= mutation_rate {
            let mutation = thread_rng().gen_range(-1.0f32, 1.0f32) * std;
            *parameter = *parameter + mutation;

            // Enforce bounds
            *parameter = f32::max(*parameter, 0_f32);
            *parameter = f32::min(*parameter, 1_f32);
        }
    }
    return parameters;
}
<|endoftext|>


<commit_before><commit_msg>Remove unnecessary Clone bound<commit_after><|endoftext|>


<commit_before><commit_msg>Sketch universe levels<commit_after>enum Level {
    Zero,
    Succ(Level),
    Max(Box<Level>, Box<Level>),
    IMax(Box<Level>, Box<Level>),
    Param(Name), // There is no way to write this currently
    Global(Name),
    Meta(Name),
}
<|endoftext|>


<commit_before><commit_msg>Implement interrupt mask level in psw register<commit_after><|endoftext|>


<commit_before><commit_msg>Fix: Compare different variables<commit_after><|endoftext|>


<commit_before><commit_msg>Add benchmarks for sqrt.<commit_after>#![feature(test, augmented_assignments)]

extern crate float;

extern crate rand;
extern crate test;

use float::Float;
use rand::{Rng, XorShiftRng};

fn random(rng: &mut XorShiftRng, p: u32) -> Float {
    let mut f = Float::rand(rng, p);
    let exp = rng.gen::<i32>();
    if rng.gen() {
        f = -f;
    }

    f.mul_exp2(exp as i64)
}

fn bench<F>(b: &mut test::Bencher, p: u32, mut f: F)
    where F: FnMut(Float) -> Float
{
    let mut rng = rand::random::<XorShiftRng>();
    b.iter(|| {
        // sqrt is somewhat dependent on the exact float it's working
        // on, so we need to test a lot of them so the differences
        // average out and hence the generation needs to be done
        // regularly
        f(random(&mut rng, p))
    })
}

macro_rules! benches {
    (with_prec $p: expr, $n: ident =>
     $($name: ident, $e: expr;)*) => {
        $(#[bench]
          fn $name(b: &mut ::test::Bencher) {
              ::bench(b, $p, |$n| $e);
          })*
    };

    ($($name: ident, $p: expr;)*) => {
        $(
            mod $name {
                #[bench]
                fn noop(b: &mut ::test::Bencher) {
                    ::bench(b, $p, |x| x)
                }

                benches!(with_prec $p, x =>
                         sqrt, x.sqrt(););
            })*
    }
}

benches! {
    p00024, 24;
    p00053, 53;
    p00100, 100;
    p01000, 1000;
    p10000, 10000;
}
<|endoftext|>


<commit_before><commit_msg>parser: add hooks to check for subcomponents properties<commit_after><|endoftext|>


<commit_before><commit_msg>parser: remove dead code<commit_after><|endoftext|>


<commit_before><commit_msg>Add arithmetic example<commit_after>// This is an implementation of the extended arithmetic server from
// Vasconcelos-Gay-Ravara (2006) with some additional functionality

#[macro_use]
extern crate session_types;
use session_types::*;

use std::thread::spawn;

// Offers: Add, Negate, Sqrt, Eval
type Srv =
    Offer<Eps,
    Offer<Recv<i64, Recv<i64, Send<i64, Var<Z>>>>,
    Offer<Recv<i64, Send<i64, Var<Z>>>,
    Offer<Recv<f64, Choose<Send<f64, Var<Z>>, Var<Z>>>,
    Recv<fn(i64) -> bool, Recv<i64, Send<bool, Var<Z>>>>>>>>;

fn server(c: Chan<(), Rec<Srv>>) {
    let mut c = c.enter();
    loop {
        c = offer!{ c,
            CLOSE => {
                c.close();
                return
            },
            ADD => {
                let (c, n) = c.recv();
                let (c, m) = c.recv();
                c.send(n + m).zero()
            },
            NEGATE => {
                let (c, n) = c.recv();
                c.send(-n).zero()
            },
            SQRT => {
                let (c, x) = c.recv();
                if x >= 0.0 {
                    c.sel1().send(x.sqrt()).zero()
                } else {
                    c.sel2().zero()
                }
            },
            EVAL => {
                let (c, f) = c.recv();
                let (c, n) = c.recv();
                c.send(f(n)).zero()
            }
        }
    }
}

// `add_client`, `neg_client` and `sqrt_client` are all pretty straightforward
// uses of session types, but they do showcase subtyping, recursion and how to
// work the types in general.

type AddCli<R> =
    Choose<Eps,
    Choose<Send<i64, Send<i64, Recv<i64, Var<Z>>>>, R>>;

fn add_client<R>(c: Chan<(), Rec<AddCli<R>>>) {
    let (c, n) = c.enter().sel2().sel1().send(42).send(1).recv();
    println!("{}", n);
    c.zero().sel1().close()
}

type NegCli<R, S> =
    Choose<Eps,
    Choose<R,
    Choose<Send<i64, Recv<i64, Var<Z>>>,
    S>>>;

fn neg_client<R, S>(c: Chan<(), Rec<NegCli<R, S>>>) {
    let (c, n) = c.enter().skip2().sel1().send(42).recv();
    println!("{}", n);
    c.zero().sel1().close();
}

type SqrtCli<R, S, T> =
    Choose<Eps,
    Choose<R,
    Choose<S,
    Choose<Send<f64, Offer<Recv<f64, Var<Z>>, Var<Z>>>,
    T>>>>;

fn sqrt_client<R, S, T>(c: Chan<(), Rec<SqrtCli<R, S, T>>>) {
    match c.enter().skip3().sel1().send(42.0).offer() {
        Left(c) => {
            let (c, n) = c.recv();
            println!("{}", n);
            c.zero().sel1().close();
        }
        Right(c) => {
            println!("Couldn't take square root!");
            c.zero().sel1().close();
        }
    }
}

// `fn_client` sends a function over the channel

type PrimeCli<R, S, T> =
    Choose<Eps,
    Choose<R,
    Choose<S,
    Choose<T,
    Send<fn(i64) -> bool, Send<i64, Recv<bool, Var<Z>>>>>>>>;

fn fn_client<R, S, T>(c: Chan<(), Rec<PrimeCli<R, S, T>>>) {
    fn even(n: i64) -> bool {
        n % 2 == 0
    }

    let (c, b) = c.enter()
        .skip4()
        .send(even)
        .send(42)
        .recv();
    println!("{}", b);
    c.zero().sel1().close();
}

// `ask_neg` and `get_neg` use delegation, that is, sending a channel over
// another channel.

// `ask_neg` selects the negation operation and sends an integer, whereafter it
// sends the whole channel to `get_neg`. `get_neg` then receives the negated
// integer and prints it.

type AskNeg<R, S> =
    Choose<Eps,
    Choose<R,
    Choose<Send<i64, Recv<i64, Var<Z>>>,
    S>>>;

fn ask_neg<R: std::marker::Send + 'static, S: std::marker::Send + 'static>(c1: Chan<(), Rec<AskNeg<R, S>>>,
                 c2: Chan<(), Send<Chan<(AskNeg<R, S>, ()), Recv<i64, Var<Z>>>, Eps>>) {
    let c1 = c1.enter().sel2().sel2().sel1().send(42);
    c2.send(c1).close();
}

fn get_neg<R: std::marker::Send + 'static, S: std::marker::Send + 'static>(c1: Chan<(), Recv<Chan<(AskNeg<R, S>, ()), Recv<i64, Var<Z>>>, Eps>>) {
    let (c1, c2) = c1.recv();
    let (c2, n) = c2.recv();
    println!("{}", n);
    c2.zero().sel1().close();
    c1.close();
}

fn main() {
    connect(server, add_client);
    connect(server, neg_client);
    connect(server, sqrt_client);
    connect(server, fn_client);

    let (c1, c1_) = session_channel();
    let (c2, c2_) = session_channel();

    let t1 = spawn(move || server(c1));
    let t2 = spawn(move || ask_neg(c1_, c2));
    let t3 = spawn(move || get_neg(c2_));

    let _ = t1.join();
    let _ = t2.join();
    let _ = t3.join();
}
<|endoftext|>


<commit_before><commit_msg>Skeleton for problem 1958<commit_after>// https://leetcode.com/problems/check-if-move-is-legal/
pub fn check_move(board: Vec<Vec<char>>, r_move: i32, c_move: i32, color: char) -> bool {
    todo!()
}

fn main() {
    println!(
        "{}",
        check_move(
            vec![
                vec!['.', '.', '.', 'B', '.', '.', '.', '.'],
                vec!['.', '.', '.', 'W', '.', '.', '.', '.'],
                vec!['.', '.', '.', 'W', '.', '.', '.', '.'],
                vec!['.', '.', '.', 'W', '.', '.', '.', '.'],
                vec!['W', 'B', 'B', '.', 'W', 'W', 'W', 'B'],
                vec!['.', '.', '.', 'B', '.', '.', '.', '.'],
                vec!['.', '.', '.', 'B', '.', '.', '.', '.'],
                vec!['.', '.', '.', 'W', '.', '.', '.', '.']
            ],
            4,
            3,
            'B'
        )
    ); // true
    println!(
        "{}",
        check_move(
            vec![
                vec!['.', '.', '.', '.', '.', '.', '.', '.'],
                vec!['.', 'B', '.', '.', 'W', '.', '.', '.'],
                vec!['.', '.', 'W', '.', '.', '.', '.', '.'],
                vec!['.', '.', '.', 'W', 'B', '.', '.', '.'],
                vec!['.', '.', '.', '.', '.', '.', '.', '.'],
                vec!['.', '.', '.', '.', 'B', 'W', '.', '.'],
                vec!['.', '.', '.', '.', '.', '.', 'W', '.'],
                vec!['.', '.', '.', '.', '.', '.', '.', 'B']
            ],
            4,
            4,
            'W'
        )
    ); // false
}
<|endoftext|>


<commit_before><commit_msg>Fix FFI definition for cairo_glyph_path<commit_after><|endoftext|>


<commit_before><commit_msg>Add regression test for #24424.<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

trait Trait1<'l0, T0> {}
trait Trait0<'l0>  {}

impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
//~^ ERROR type annotations required: cannot resolve `T0: Trait0<'l0>`
//~^^ NOTE required by `Trait0`

fn main() {}
<|endoftext|>


<commit_before><commit_msg>Add todo module<commit_after>use super::Module;
use std::path::Path;

pub struct TodoModule {
    path: Option<String>,
}

impl Module for TodoModule {

    fn new(rt : &Runtime) -> TodoModule {
        TodoModule {
            path: None
        }
    }

    fn name(&self) -> String {
        "Todo".to_string()
    }

    fn execute(&self, rt : &Runtime) -> Option<Error> {
        ( )
    }
}
<|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/. */

extern mod freetype;
extern mod fontconfig;

use fontconfig::fontconfig::{
    FcChar8, FcResultMatch, FcSetSystem,
    FcResultNoMatch, FcMatchPattern, FC_SLANT_ITALIC, FC_WEIGHT_BOLD
};
use fontconfig::fontconfig::bindgen::{
    FcConfigGetCurrent, FcConfigGetFonts, FcPatternGetString,
    FcPatternDestroy, FcFontSetDestroy, FcConfigSubstitute,
    FcDefaultSubstitute, FcPatternCreate, FcPatternAddString, FcPatternAddInteger,
    FcFontMatch, FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
    FcObjectSetAdd, FcPatternGetInteger
};

use font::{FontHandleMethods, UsedFontStyle};
use font_context::FontContextHandleMethods;
use font_list::{FontEntry, FontFamily, FontFamilyMap};
use platform::font::FontHandle;
use platform::font_context::FontContextHandle;

use core::hashmap::HashMap;
use core::libc::c_int;
use core::ptr::Ptr;

pub struct FontListHandle {
    fctx: FontContextHandle,
}

pub impl FontListHandle {
    pub fn new(fctx: &FontContextHandle) -> FontListHandle {
        FontListHandle { fctx: fctx.clone() }
    }

    fn get_available_families(&self) -> FontFamilyMap {
        let mut family_map : FontFamilyMap = HashMap::new();
        unsafe {
            let config = FcConfigGetCurrent();
            let fontSet = FcConfigGetFonts(config, FcSetSystem);
            for uint::range(0, (*fontSet).nfont as uint) |i| {
                let font = (*fontSet).fonts.offset(i);
                let family: *FcChar8 = ptr::null();
                let mut v: c_int = 0;
                do str::as_c_str("family") |FC_FAMILY| {
                    while FcPatternGetString(*font, FC_FAMILY, v, &family) == FcResultMatch {
                        let family_name = str::raw::from_buf(family as *u8);
                        debug!("Creating new FontFamily for family: %s", family_name);
                        let new_family = @mut FontFamily::new(family_name);
                        family_map.insert(family_name, new_family);
                        v += 1;
                    }
                }
            }
        }
        return family_map;
    }

    fn load_variations_for_family(&self, family: @mut FontFamily) {
        debug!("getting variations for %?", family);
        let config = FcConfigGetCurrent();
        let font_set = FcConfigGetFonts(config, FcSetSystem);
        let font_set_array_ptr = ptr::to_unsafe_ptr(&font_set);
        unsafe {
            let pattern = FcPatternCreate();
            assert!(pattern.is_not_null());
            do str::as_c_str("family") |FC_FAMILY| {
                do str::as_c_str(family.family_name) |family_name| {
                    let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8);
                    assert!(ok != 0);
                }
            }

            let object_set = FcObjectSetCreate();
            assert!(object_set.is_not_null());

            do str::as_c_str("file") |FC_FILE| {
                FcObjectSetAdd(object_set, FC_FILE);
            }
            do str::as_c_str("index") |FC_INDEX| {
                FcObjectSetAdd(object_set, FC_INDEX);
            }

            let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set);

            debug!("found %? variations", (*matches).nfont);

            for uint::range(0, (*matches).nfont as uint) |i| {
                let font = (*matches).fonts.offset(i);
                let file = do str::as_c_str("file") |FC_FILE| {
                    let file: *FcChar8 = ptr::null();
                    if FcPatternGetString(*font, FC_FILE, 0, &file) == FcResultMatch {
                        str::raw::from_c_str(file as *libc::c_char)
                    } else {
                        fail!();
                    }
                };
                let index = do str::as_c_str("index") |FC_INDEX| {
                    let index: libc::c_int = 0;
                    if FcPatternGetInteger(*font, FC_INDEX, 0, &index) == FcResultMatch {
                        index
                    } else {
                        fail!();
                    }
                };

                debug!("variation file: %?", file);
                debug!("variation index: %?", index);

                let font_handle = FontHandle::new_from_file_unstyled(&self.fctx,
                                                                     file);
                let font_handle = font_handle.unwrap();

                debug!("Creating new FontEntry for face: %s", font_handle.face_name());
                let entry = @FontEntry::new(family, font_handle);
                family.entries.push(entry);
            }

            FcFontSetDestroy(matches);
            FcPatternDestroy(pattern);
            FcObjectSetDestroy(object_set);
        }
    }
}

pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, ()> {
    unsafe {
        let config = FcConfigGetCurrent();
        let pattern = FcPatternCreate();
        let res = do str::as_c_str("family") |FC_FAMILY| {
            do str::as_c_str(name) |family| {
                FcPatternAddString(pattern, FC_FAMILY, family as *FcChar8)
            }
        };
        if res != 1 {
            debug!("adding family to pattern failed");
            return Err(());
        }

        if style.italic {
            let res = do str::as_c_str("slant") |FC_SLANT| {
                FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC)
            };
            if res != 1 {
                debug!("adding slant to pattern failed");
                return Err(());
            }
        }
        if style.weight.is_bold() {
            let res = do str::as_c_str("weight") |FC_WEIGHT| {
                FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD)
            };
            if res != 1 {
                debug!("adding weight to pattern failed");
                return Err(());
            }
        }

        if FcConfigSubstitute(config, pattern, FcMatchPattern) != 1 {
            debug!("substitution failed");
            return Err(());
        }
        FcDefaultSubstitute(pattern);
        let result = FcResultNoMatch;
        let result_pattern = FcFontMatch(config, pattern, &result);
        if result != FcResultMatch && result_pattern.is_null() {
            debug!("obtaining match to pattern failed");
            return Err(());
        }

        let file: *FcChar8 = ptr::null();
        let res = do str::as_c_str("file") |FC_FILE| {
            FcPatternGetString(result_pattern, FC_FILE, 0, &file)
        };
        if res != FcResultMatch {
            debug!("getting filename for font failed");
            return Err(());
        }
        Ok(str::raw::from_buf(file as *u8))
    }
}
<commit_msg>Avoid leaking FcPattern pointers.<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/. */

extern mod freetype;
extern mod fontconfig;

use fontconfig::fontconfig::{
    FcChar8, FcResultMatch, FcSetSystem, FcPattern,
    FcResultNoMatch, FcMatchPattern, FC_SLANT_ITALIC, FC_WEIGHT_BOLD
};
use fontconfig::fontconfig::bindgen::{
    FcConfigGetCurrent, FcConfigGetFonts, FcPatternGetString,
    FcPatternDestroy, FcFontSetDestroy, FcConfigSubstitute,
    FcDefaultSubstitute, FcPatternCreate, FcPatternAddString, FcPatternAddInteger,
    FcFontMatch, FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
    FcObjectSetAdd, FcPatternGetInteger
};

use font::{FontHandleMethods, UsedFontStyle};
use font_context::FontContextHandleMethods;
use font_list::{FontEntry, FontFamily, FontFamilyMap};
use platform::font::FontHandle;
use platform::font_context::FontContextHandle;

use core::hashmap::HashMap;
use core::libc::c_int;
use core::ptr::Ptr;

pub struct FontListHandle {
    fctx: FontContextHandle,
}

pub impl FontListHandle {
    pub fn new(fctx: &FontContextHandle) -> FontListHandle {
        FontListHandle { fctx: fctx.clone() }
    }

    fn get_available_families(&self) -> FontFamilyMap {
        let mut family_map : FontFamilyMap = HashMap::new();
        unsafe {
            let config = FcConfigGetCurrent();
            let fontSet = FcConfigGetFonts(config, FcSetSystem);
            for uint::range(0, (*fontSet).nfont as uint) |i| {
                let font = (*fontSet).fonts.offset(i);
                let family: *FcChar8 = ptr::null();
                let mut v: c_int = 0;
                do str::as_c_str("family") |FC_FAMILY| {
                    while FcPatternGetString(*font, FC_FAMILY, v, &family) == FcResultMatch {
                        let family_name = str::raw::from_buf(family as *u8);
                        debug!("Creating new FontFamily for family: %s", family_name);
                        let new_family = @mut FontFamily::new(family_name);
                        family_map.insert(family_name, new_family);
                        v += 1;
                    }
                }
            }
        }
        return family_map;
    }

    fn load_variations_for_family(&self, family: @mut FontFamily) {
        debug!("getting variations for %?", family);
        let config = FcConfigGetCurrent();
        let font_set = FcConfigGetFonts(config, FcSetSystem);
        let font_set_array_ptr = ptr::to_unsafe_ptr(&font_set);
        unsafe {
            let pattern = FcPatternCreate();
            assert!(pattern.is_not_null());
            do str::as_c_str("family") |FC_FAMILY| {
                do str::as_c_str(family.family_name) |family_name| {
                    let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8);
                    assert!(ok != 0);
                }
            }

            let object_set = FcObjectSetCreate();
            assert!(object_set.is_not_null());

            do str::as_c_str("file") |FC_FILE| {
                FcObjectSetAdd(object_set, FC_FILE);
            }
            do str::as_c_str("index") |FC_INDEX| {
                FcObjectSetAdd(object_set, FC_INDEX);
            }

            let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set);

            debug!("found %? variations", (*matches).nfont);

            for uint::range(0, (*matches).nfont as uint) |i| {
                let font = (*matches).fonts.offset(i);
                let file = do str::as_c_str("file") |FC_FILE| {
                    let file: *FcChar8 = ptr::null();
                    if FcPatternGetString(*font, FC_FILE, 0, &file) == FcResultMatch {
                        str::raw::from_c_str(file as *libc::c_char)
                    } else {
                        fail!();
                    }
                };
                let index = do str::as_c_str("index") |FC_INDEX| {
                    let index: libc::c_int = 0;
                    if FcPatternGetInteger(*font, FC_INDEX, 0, &index) == FcResultMatch {
                        index
                    } else {
                        fail!();
                    }
                };

                debug!("variation file: %?", file);
                debug!("variation index: %?", index);

                let font_handle = FontHandle::new_from_file_unstyled(&self.fctx,
                                                                     file);
                let font_handle = font_handle.unwrap();

                debug!("Creating new FontEntry for face: %s", font_handle.face_name());
                let entry = @FontEntry::new(family, font_handle);
                family.entries.push(entry);
            }

            FcFontSetDestroy(matches);
            FcPatternDestroy(pattern);
            FcObjectSetDestroy(object_set);
        }
    }
}

struct AutoPattern {
    pattern: *FcPattern
}

impl Drop for AutoPattern {
    fn finalize(&self) {
        FcPatternDestroy(self.pattern);
    }
}

pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, ()> {
    unsafe {
        let config = FcConfigGetCurrent();
        let wrapper = AutoPattern { pattern: FcPatternCreate() };
        let pattern = wrapper.pattern;
        let res = do str::as_c_str("family") |FC_FAMILY| {
            do str::as_c_str(name) |family| {
                FcPatternAddString(pattern, FC_FAMILY, family as *FcChar8)
            }
        };
        if res != 1 {
            debug!("adding family to pattern failed");
            return Err(());
        }

        if style.italic {
            let res = do str::as_c_str("slant") |FC_SLANT| {
                FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC)
            };
            if res != 1 {
                debug!("adding slant to pattern failed");
                return Err(());
            }
        }
        if style.weight.is_bold() {
            let res = do str::as_c_str("weight") |FC_WEIGHT| {
                FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD)
            };
            if res != 1 {
                debug!("adding weight to pattern failed");
                return Err(());
            }
        }

        if FcConfigSubstitute(config, pattern, FcMatchPattern) != 1 {
            debug!("substitution failed");
            return Err(());
        }
        FcDefaultSubstitute(pattern);
        let result = FcResultNoMatch;
        let result_wrapper = AutoPattern { pattern: FcFontMatch(config, pattern, &result) };
        let result_pattern = result_wrapper.pattern;
        if result != FcResultMatch && result_pattern.is_null() {
            debug!("obtaining match to pattern failed");
            return Err(());
        }

        let file: *FcChar8 = ptr::null();
        let res = do str::as_c_str("file") |FC_FILE| {
            FcPatternGetString(result_pattern, FC_FILE, 0, &file)
        };
        if res != FcResultMatch {
            debug!("getting filename for font failed");
            return Err(());
        }
        Ok(str::raw::from_buf(file as *u8))
    }
}
<|endoftext|>