<commit_before>use index::btree::external::ExtNode;
use index::btree::insert::check_root_modification;
use index::btree::internal::InNode;
use index::btree::node::read_node;
use index::btree::node::read_unchecked;
use index::btree::node::write_node;
use index::btree::node::write_non_empty;
use index::btree::node::write_targeted;
use index::btree::node::Node;
use index::btree::node::NodeData;
use index::btree::node::NodeReadHandler;
use index::btree::search::mut_search;
use index::btree::search::MutSearchResult;
use index::btree::BPlusTree;
use index::btree::NodeCellRef;
use index::EntryKey;
use index::Slice;
use itertools::Itertools;
use std::fmt::Debug;

enum MergeSearch {
    External,
    Internal(NodeCellRef),
    RightNode(NodeCellRef),
}

fn merge_into_internal<KS, PS>(
    node: &NodeCellRef,
    lower_level_new_pages: Box<Vec<(EntryKey, NodeCellRef)>>,
    new_pages: &mut Vec<(EntryKey, NodeCellRef)>,
) where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let mut node_guard = write_node::<KS, PS>(node);
    for (pivot, node) in lower_level_new_pages.into_iter() {
        let mut target_guard = write_non_empty(write_targeted(node_guard, &pivot));
        {
            debug_assert!(!target_guard.is_none());
            let innode = target_guard.innode_mut();
            let pos = innode.search(&pivot);
            if innode.len == KS::slice_len() - 1 {
                // TODO: check boundary
                // full node, going to split
                let (node_ref, key) = innode.split_insert(pivot, node, pos, true);
                new_pages.push((key, node_ref));
            } else {
                innode.insert_in_place(pivot, node, pos, true);
            }
        }
        node_guard = target_guard;
    }
}

fn debug_check_serialized(keys: &Vec<EntryKey>) {
    if cfg!(debug_assertions) && keys.len() > 0 {
        for i in 0..keys.len() - 1 {
            let left = &keys[i];
            let right = &keys[i + 1];
            assert!(left < right, "at {}, {:?} >= {:?}", i, left, right);
        }
    }
}

pub fn merge_into_tree_node<KS, PS>(
    tree: &BPlusTree<KS, PS>,
    node: &NodeCellRef,
    _parent: &NodeCellRef,
    keys: Box<Vec<EntryKey>>,
    level: usize,
) -> Box<Vec<(EntryKey, NodeCellRef)>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    debug_check_serialized(&*keys);
    let search = mut_search::<KS, PS>(node, &keys[0]);
    let new_pages = match search {
        MutSearchResult::External => {
            // merge keys into internal pages
            // this is a oneshot action.
            // after the merge, it will return all new inserted new pages to upper level
            debug!("Merge into internal with keys {:?}", &keys);
            let keys_len = keys.len();
            let mut merging_pos = 0;
            let mut current_guard = write_node::<KS, PS>(&node);
            let mut new_pages = vec![];
            // merge by pages
            while merging_pos < keys_len {
                let start_key = &keys[merging_pos];
                debug!("Start merging with page at {:?}", start_key);
                current_guard = write_targeted(current_guard, start_key);
                let remain_slots = KS::slice_len() - current_guard.len();
                ExtNode::<KS, PS>::make_changed(current_guard.node_ref(), tree);
                if remain_slots > 0 {
                    let mut ext_node = current_guard.extnode_mut();
                    ext_node.remove_contains(&mut *tree.deleted.write());
                    let selection = keys[merging_pos..keys_len]
                        .iter()
                        .filter(|&k| k < &ext_node.right_bound)
                        .take(remain_slots)
                        .collect_vec();
                    ext_node.merge_sort(selection.as_slice());
                    merging_pos += selection.len();
                } else if remain_slots == 0 {
                    let insert_pos = current_guard.search(&start_key);
                    let target_node_ref = current_guard.node_ref().clone();
                    let mut right_guard =
                        write_node::<KS, PS>(current_guard.right_ref_mut_no_empty().unwrap());
                    let (new_node, pivot) = current_guard.extnode_mut().split_insert(
                        start_key.clone(),
                        insert_pos,
                        &target_node_ref,
                        &mut right_guard,
                        tree,
                    );
                    merging_pos += 1;
                    ExtNode::<KS, PS>::make_changed(&new_node, tree);
                    new_pages.push((pivot, new_node));
                }
            }
            new_pages
        }
        MutSearchResult::Internal(sub_node) => {
            debug_assert!(!sub_node.is_default());
            let lower_level_new_pages =
                merge_into_tree_node(tree, &sub_node, node, keys, level + 1);
            let mut new_pages = vec![];
            if lower_level_new_pages.len() > 0 {
                merge_into_internal::<KS, PS>(node, lower_level_new_pages, &mut new_pages);
            }
            new_pages
        }
    };
    if level == 0 && new_pages.len() > 0 {
        // it is impossible to have a node been changed during merge for merges are performed in serial
        debug_assert_eq!(
            read_unchecked::<KS, PS>(&tree.get_root()).first_key(),
            read_unchecked::<KS, PS>(&node).first_key()
        )
    }
    return box new_pages;
}
<commit_msg>more robust bound check<commit_after>use index::btree::external::ExtNode;
use index::btree::insert::check_root_modification;
use index::btree::internal::InNode;
use index::btree::node::read_node;
use index::btree::node::read_unchecked;
use index::btree::node::write_node;
use index::btree::node::write_non_empty;
use index::btree::node::write_targeted;
use index::btree::node::Node;
use index::btree::node::NodeData;
use index::btree::node::NodeReadHandler;
use index::btree::search::mut_search;
use index::btree::search::MutSearchResult;
use index::btree::BPlusTree;
use index::btree::NodeCellRef;
use index::EntryKey;
use index::Slice;
use itertools::Itertools;
use std::fmt::Debug;

enum MergeSearch {
    External,
    Internal(NodeCellRef),
    RightNode(NodeCellRef),
}

fn merge_into_internal<KS, PS>(
    node: &NodeCellRef,
    lower_level_new_pages: Box<Vec<(EntryKey, NodeCellRef)>>,
    new_pages: &mut Vec<(EntryKey, NodeCellRef)>,
) where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let mut node_guard = write_node::<KS, PS>(node);
    for (pivot, node) in lower_level_new_pages.into_iter() {
        let mut target_guard = write_non_empty(write_targeted(node_guard, &pivot));
        {
            debug_assert!(!target_guard.is_none());
            let innode = target_guard.innode_mut();
            let pos = innode.search(&pivot);
            if innode.len >= KS::slice_len() {
                // TODO: check boundary
                // full node, going to split
                let (node_ref, key) = innode.split_insert(pivot, node, pos, true);
                new_pages.push((key, node_ref));
            } else {
                innode.insert_in_place(pivot, node, pos, true);
            }
        }
        node_guard = target_guard;
    }
}

fn debug_check_serialized(keys: &Vec<EntryKey>) {
    if cfg!(debug_assertions) && keys.len() > 0 {
        for i in 0..keys.len() - 1 {
            let left = &keys[i];
            let right = &keys[i + 1];
            assert!(left < right, "at {}, {:?} >= {:?}", i, left, right);
        }
    }
}

pub fn merge_into_tree_node<KS, PS>(
    tree: &BPlusTree<KS, PS>,
    node: &NodeCellRef,
    _parent: &NodeCellRef,
    keys: Box<Vec<EntryKey>>,
    level: usize,
) -> Box<Vec<(EntryKey, NodeCellRef)>>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    debug_check_serialized(&*keys);
    let search = mut_search::<KS, PS>(node, &keys[0]);
    let new_pages = match search {
        MutSearchResult::External => {
            // merge keys into internal pages
            // this is a oneshot action.
            // after the merge, it will return all new inserted new pages to upper level
            debug!("Merge into internal with keys {:?}", &keys);
            let keys_len = keys.len();
            let mut merging_pos = 0;
            let mut current_guard = write_node::<KS, PS>(&node);
            let mut new_pages = vec![];
            // merge by pages
            while merging_pos < keys_len {
                let start_key = &keys[merging_pos];
                debug!("Start merging with page at {:?}", start_key);
                current_guard = write_targeted(current_guard, start_key);
                let remain_slots = KS::slice_len() - current_guard.len();
                ExtNode::<KS, PS>::make_changed(current_guard.node_ref(), tree);
                if remain_slots > 0 {
                    let mut ext_node = current_guard.extnode_mut();
                    ext_node.remove_contains(&mut *tree.deleted.write());
                    let selection = keys[merging_pos..keys_len]
                        .iter()
                        .filter(|&k| k < &ext_node.right_bound)
                        .take(remain_slots)
                        .collect_vec();
                    ext_node.merge_sort(selection.as_slice());
                    merging_pos += selection.len();
                } else if remain_slots == 0 {
                    let insert_pos = current_guard.search(&start_key);
                    let target_node_ref = current_guard.node_ref().clone();
                    let mut right_guard =
                        write_node::<KS, PS>(current_guard.right_ref_mut_no_empty().unwrap());
                    let (new_node, pivot) = current_guard.extnode_mut().split_insert(
                        start_key.clone(),
                        insert_pos,
                        &target_node_ref,
                        &mut right_guard,
                        tree,
                    );
                    merging_pos += 1;
                    ExtNode::<KS, PS>::make_changed(&new_node, tree);
                    new_pages.push((pivot, new_node));
                }
            }
            new_pages
        }
        MutSearchResult::Internal(sub_node) => {
            debug_assert!(!sub_node.is_default());
            let lower_level_new_pages =
                merge_into_tree_node(tree, &sub_node, node, keys, level + 1);
            let mut new_pages = vec![];
            if lower_level_new_pages.len() > 0 {
                merge_into_internal::<KS, PS>(node, lower_level_new_pages, &mut new_pages);
            }
            new_pages
        }
    };
    if level == 0 && new_pages.len() > 0 {
        // it is impossible to have a node been changed during merge for merges are performed in serial
        debug_assert_eq!(
            read_unchecked::<KS, PS>(&tree.get_root()).first_key(),
            read_unchecked::<KS, PS>(&node).first_key()
        )
    }
    return box new_pages;
}
<|endoftext|>


<commit_before>// Copyright 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.

//! C definitions used by libnative that don't belong in liblibc

#![allow(dead_code)]
#![allow(non_camel_case_types)]

pub use self::select::fd_set;
pub use self::signal::{sigaction, siginfo, sigset_t};
pub use self::signal::{SA_ONSTACK, SA_RESTART, SA_RESETHAND, SA_NOCLDSTOP};
pub use self::signal::{SA_NODEFER, SA_NOCLDWAIT, SA_SIGINFO, SIGCHLD};

use libc;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const FIONBIO: libc::c_ulong = 0x8004667e;
#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm")),
          target_os = "android"))]
pub const FIONBIO: libc::c_ulong = 0x5421;
#[cfg(all(target_os = "linux",
          any(target_arch = "mips", target_arch = "mipsel")))]
pub const FIONBIO: libc::c_ulong = 0x667e;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const FIOCLEX: libc::c_ulong = 0x20006601;
#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm")),
          target_os = "android"))]
pub const FIOCLEX: libc::c_ulong = 0x5451;
#[cfg(all(target_os = "linux",
          any(target_arch = "mips", target_arch = "mipsel")))]
pub const FIOCLEX: libc::c_ulong = 0x6601;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const MSG_DONTWAIT: libc::c_int = 0x80;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub const MSG_DONTWAIT: libc::c_int = 0x40;

pub const WNOHANG: libc::c_int = 1;

extern {
    pub fn gettimeofday(timeval: *mut libc::timeval,
                        tzp: *mut libc::c_void) -> libc::c_int;
    pub fn select(nfds: libc::c_int,
                  readfds: *mut fd_set,
                  writefds: *mut fd_set,
                  errorfds: *mut fd_set,
                  timeout: *mut libc::timeval) -> libc::c_int;
    pub fn getsockopt(sockfd: libc::c_int,
                      level: libc::c_int,
                      optname: libc::c_int,
                      optval: *mut libc::c_void,
                      optlen: *mut libc::socklen_t) -> libc::c_int;
    pub fn ioctl(fd: libc::c_int, req: libc::c_ulong, ...) -> libc::c_int;

    pub fn waitpid(pid: libc::pid_t, status: *mut libc::c_int,
                   options: libc::c_int) -> libc::pid_t;

    pub fn sigaction(signum: libc::c_int,
                     act: *const sigaction,
                     oldact: *mut sigaction) -> libc::c_int;

    pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
    pub fn sigdelset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
    pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
mod select {
    pub const FD_SETSIZE: uint = 1024;

    #[repr(C)]
    pub struct fd_set {
        fds_bits: [i32, ..(FD_SETSIZE / 32)]
    }

    pub fn fd_set(set: &mut fd_set, fd: i32) {
        set.fds_bits[(fd / 32) as uint] |= 1 << ((fd % 32) as uint);
    }
}

#[cfg(any(target_os = "android",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "linux"))]
mod select {
    use uint;
    use libc;

    pub const FD_SETSIZE: uint = 1024;

    #[repr(C)]
    pub struct fd_set {
        // FIXME: shouldn't this be a c_ulong?
        fds_bits: [libc::uintptr_t, ..(FD_SETSIZE / uint::BITS)]
    }

    pub fn fd_set(set: &mut fd_set, fd: i32) {
        let fd = fd as uint;
        set.fds_bits[fd / uint::BITS] |= 1 << (fd % uint::BITS);
    }
}

#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm")),
          target_os = "android"))]
mod signal {
    use libc;

    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00000002;
    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
    pub const SA_RESTART: libc::c_ulong = 0x10000000;
    pub const SA_SIGINFO: libc::c_ulong = 0x00000004;
    pub const SIGCHLD: libc::c_int = 17;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_errno: libc::c_int,
        si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        pub sa_flags: libc::c_ulong,
        sa_restorer: *mut libc::c_void,
    }

    unsafe impl ::kinds::Send for sigaction { }
    unsafe impl ::kinds::Sync for sigaction { }

    #[repr(C)]
    #[cfg(target_word_size = "32")]
    pub struct sigset_t {
        __val: [libc::c_ulong, ..32],
    }

    #[repr(C)]
    #[cfg(target_word_size = "64")]
    pub struct sigset_t {
        __val: [libc::c_ulong, ..16],
    }
}

#[cfg(all(target_os = "linux",
          any(target_arch = "mips", target_arch = "mipsel")))]
mod signal {
    use libc;

    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00010000;
    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
    pub const SA_RESTART: libc::c_ulong = 0x10000000;
    pub const SA_SIGINFO: libc::c_ulong = 0x00000008;
    pub const SIGCHLD: libc::c_int = 18;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_code: libc::c_int,
        si_errno: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_flags: libc::c_uint,
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        sa_restorer: *mut libc::c_void,
        sa_resv: [libc::c_int, ..1],
    }

    impl ::kinds::Send for sigaction { }
    impl ::kinds::Sync for sigaction { }

    #[repr(C)]
    pub struct sigset_t {
        __val: [libc::c_ulong, ..32],
    }
}

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
mod signal {
    use libc;

    pub const SA_ONSTACK: libc::c_int = 0x0001;
    pub const SA_RESTART: libc::c_int = 0x0002;
    pub const SA_RESETHAND: libc::c_int = 0x0004;
    pub const SA_NOCLDSTOP: libc::c_int = 0x0008;
    pub const SA_NODEFER: libc::c_int = 0x0010;
    pub const SA_NOCLDWAIT: libc::c_int = 0x0020;
    pub const SA_SIGINFO: libc::c_int = 0x0040;
    pub const SIGCHLD: libc::c_int = 20;

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    pub type sigset_t = u32;
    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
    #[repr(C)]
    pub struct sigset_t {
        bits: [u32, ..4],
    }

    // This structure has more fields, but we're not all that interested in
    // them.
    #[repr(C)]
    pub struct siginfo {
        pub si_signo: libc::c_int,
        pub si_errno: libc::c_int,
        pub si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_flags: libc::c_int,
        pub sa_mask: sigset_t,
    }
}
<commit_msg>rollup merge of #20321: epall/patch-1<commit_after>// Copyright 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.

//! C definitions used by libnative that don't belong in liblibc

#![allow(dead_code)]
#![allow(non_camel_case_types)]

pub use self::select::fd_set;
pub use self::signal::{sigaction, siginfo, sigset_t};
pub use self::signal::{SA_ONSTACK, SA_RESTART, SA_RESETHAND, SA_NOCLDSTOP};
pub use self::signal::{SA_NODEFER, SA_NOCLDWAIT, SA_SIGINFO, SIGCHLD};

use libc;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const FIONBIO: libc::c_ulong = 0x8004667e;
#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm")),
          target_os = "android"))]
pub const FIONBIO: libc::c_ulong = 0x5421;
#[cfg(all(target_os = "linux",
          any(target_arch = "mips", target_arch = "mipsel")))]
pub const FIONBIO: libc::c_ulong = 0x667e;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const FIOCLEX: libc::c_ulong = 0x20006601;
#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm")),
          target_os = "android"))]
pub const FIOCLEX: libc::c_ulong = 0x5451;
#[cfg(all(target_os = "linux",
          any(target_arch = "mips", target_arch = "mipsel")))]
pub const FIOCLEX: libc::c_ulong = 0x6601;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const MSG_DONTWAIT: libc::c_int = 0x80;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub const MSG_DONTWAIT: libc::c_int = 0x40;

pub const WNOHANG: libc::c_int = 1;

extern {
    pub fn gettimeofday(timeval: *mut libc::timeval,
                        tzp: *mut libc::c_void) -> libc::c_int;
    pub fn select(nfds: libc::c_int,
                  readfds: *mut fd_set,
                  writefds: *mut fd_set,
                  errorfds: *mut fd_set,
                  timeout: *mut libc::timeval) -> libc::c_int;
    pub fn getsockopt(sockfd: libc::c_int,
                      level: libc::c_int,
                      optname: libc::c_int,
                      optval: *mut libc::c_void,
                      optlen: *mut libc::socklen_t) -> libc::c_int;
    pub fn ioctl(fd: libc::c_int, req: libc::c_ulong, ...) -> libc::c_int;

    pub fn waitpid(pid: libc::pid_t, status: *mut libc::c_int,
                   options: libc::c_int) -> libc::pid_t;

    pub fn sigaction(signum: libc::c_int,
                     act: *const sigaction,
                     oldact: *mut sigaction) -> libc::c_int;

    pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
    pub fn sigdelset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
    pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
mod select {
    pub const FD_SETSIZE: uint = 1024;

    #[repr(C)]
    pub struct fd_set {
        fds_bits: [i32, ..(FD_SETSIZE / 32)]
    }

    pub fn fd_set(set: &mut fd_set, fd: i32) {
        set.fds_bits[(fd / 32) as uint] |= 1 << ((fd % 32) as uint);
    }
}

#[cfg(any(target_os = "android",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "linux"))]
mod select {
    use uint;
    use libc;

    pub const FD_SETSIZE: uint = 1024;

    #[repr(C)]
    pub struct fd_set {
        // FIXME: shouldn't this be a c_ulong?
        fds_bits: [libc::uintptr_t, ..(FD_SETSIZE / uint::BITS)]
    }

    pub fn fd_set(set: &mut fd_set, fd: i32) {
        let fd = fd as uint;
        set.fds_bits[fd / uint::BITS] |= 1 << (fd % uint::BITS);
    }
}

#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm")),
          target_os = "android"))]
mod signal {
    use libc;

    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00000002;
    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
    pub const SA_RESTART: libc::c_ulong = 0x10000000;
    pub const SA_SIGINFO: libc::c_ulong = 0x00000004;
    pub const SIGCHLD: libc::c_int = 17;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_errno: libc::c_int,
        si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        pub sa_flags: libc::c_ulong,
        sa_restorer: *mut libc::c_void,
    }

    unsafe impl ::kinds::Send for sigaction { }
    unsafe impl ::kinds::Sync for sigaction { }

    #[repr(C)]
    #[cfg(target_word_size = "32")]
    pub struct sigset_t {
        __val: [libc::c_ulong, ..32],
    }

    #[repr(C)]
    #[cfg(target_word_size = "64")]
    pub struct sigset_t {
        __val: [libc::c_ulong, ..16],
    }
}

#[cfg(all(target_os = "linux",
          any(target_arch = "mips", target_arch = "mipsel")))]
mod signal {
    use libc;

    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00010000;
    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
    pub const SA_RESTART: libc::c_ulong = 0x10000000;
    pub const SA_SIGINFO: libc::c_ulong = 0x00000008;
    pub const SIGCHLD: libc::c_int = 18;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_code: libc::c_int,
        si_errno: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_flags: libc::c_uint,
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        sa_restorer: *mut libc::c_void,
        sa_resv: [libc::c_int, ..1],
    }

    unsafe impl ::kinds::Send for sigaction { }
    unsafe impl ::kinds::Sync for sigaction { }

    #[repr(C)]
    pub struct sigset_t {
        __val: [libc::c_ulong, ..32],
    }
}

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
mod signal {
    use libc;

    pub const SA_ONSTACK: libc::c_int = 0x0001;
    pub const SA_RESTART: libc::c_int = 0x0002;
    pub const SA_RESETHAND: libc::c_int = 0x0004;
    pub const SA_NOCLDSTOP: libc::c_int = 0x0008;
    pub const SA_NODEFER: libc::c_int = 0x0010;
    pub const SA_NOCLDWAIT: libc::c_int = 0x0020;
    pub const SA_SIGINFO: libc::c_int = 0x0040;
    pub const SIGCHLD: libc::c_int = 20;

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    pub type sigset_t = u32;
    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
    #[repr(C)]
    pub struct sigset_t {
        bits: [u32, ..4],
    }

    // This structure has more fields, but we're not all that interested in
    // them.
    #[repr(C)]
    pub struct siginfo {
        pub si_signo: libc::c_int,
        pub si_errno: libc::c_int,
        pub si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_flags: libc::c_int,
        pub sa_mask: sigset_t,
    }
}
<|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.

use core::prelude::*;

use abi::AbiSet;
use ast::*;
use ast;
use ast_util::{inlined_item_utils, stmt_id};
use ast_util;
use codemap;
use diagnostic::span_handler;
use parse::token::ident_interner;
use print::pprust;
use visit;
use syntax::parse::token::special_idents;

use core::cmp;
use core::hashmap::HashMap;
use core::str;
use core::vec;

pub enum path_elt {
    path_mod(ident),
    path_name(ident)
}

impl cmp::Eq for path_elt {
    fn eq(&self, other: &path_elt) -> bool {
        match (*self) {
            path_mod(e0a) => {
                match (*other) {
                    path_mod(e0b) => e0a == e0b,
                    _ => false
                }
            }
            path_name(e0a) => {
                match (*other) {
                    path_name(e0b) => e0a == e0b,
                    _ => false
                }
            }
        }
    }
    fn ne(&self, other: &path_elt) -> bool { !(*self).eq(other) }
}

pub type path = ~[path_elt];

pub fn path_to_str_with_sep(p: &[path_elt], sep: ~str, itr: @ident_interner)
                         -> ~str {
    let strs = do p.map |e| {
        match *e {
          path_mod(s) => copy *itr.get(s),
          path_name(s) => copy *itr.get(s)
        }
    };
    str::connect(strs, sep)
}

pub fn path_ident_to_str(p: &path, i: ident, itr: @ident_interner) -> ~str {
    if vec::is_empty(*p) {
        //FIXME /* FIXME (#2543) */ copy *i
        copy *itr.get(i)
    } else {
        fmt!("%s::%s", path_to_str(*p, itr), *itr.get(i))
    }
}

pub fn path_to_str(p: &[path_elt], itr: @ident_interner) -> ~str {
    path_to_str_with_sep(p, ~"::", itr)
}

pub fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str {
    match pe {
        path_mod(s) => copy *itr.get(s),
        path_name(s) => copy *itr.get(s)
    }
}

pub enum ast_node {
    node_item(@item, @path),
    node_foreign_item(@foreign_item, AbiSet, visibility, @path),
    node_trait_method(@trait_method, def_id /* trait did */,
                      @path /* path to the trait */),
    node_method(@method, def_id /* impl did */, @path /* path to the impl */),
    node_variant(variant, @item, @path),
    node_expr(@expr),
    node_stmt(@stmt),
    node_arg,
    node_local(ident),
    node_block(blk),
    node_struct_ctor(@struct_def, @item, @path),
    node_callee_scope(@expr)
}

pub type map = @mut HashMap<node_id, ast_node>;

pub struct Ctx {
    map: map,
    path: path,
    diag: @span_handler,
}

pub type vt = visit::vt<@mut Ctx>;

pub fn extend(cx: @mut Ctx, elt: ident) -> @path {
    @(vec::append(copy cx.path, [path_name(elt)]))
}

pub fn mk_ast_map_visitor() -> vt {
    return visit::mk_vt(@visit::Visitor {
        visit_item: map_item,
        visit_expr: map_expr,
        visit_stmt: map_stmt,
        visit_fn: map_fn,
        visit_block: map_block,
        visit_pat: map_pat,
        .. *visit::default_visitor()
    });
}

pub fn map_crate(diag: @span_handler, c: @crate) -> map {
    let cx = @mut Ctx {
        map: @mut HashMap::new(),
        path: ~[],
        diag: diag,
    };
    visit::visit_crate(c, cx, mk_ast_map_visitor());
    cx.map
}

// Used for items loaded from external crate that are being inlined into this
// crate.  The `path` should be the path to the item but should not include
// the item itself.
pub fn map_decoded_item(diag: @span_handler,
                        map: map,
                        path: path,
                        ii: &inlined_item) {
    // I believe it is ok for the local IDs of inlined items from other crates
    // to overlap with the local ids from this crate, so just generate the ids
    // starting from 0.  (In particular, I think these ids are only used in
    // alias analysis, which we will not be running on the inlined items, and
    // even if we did I think it only needs an ordering between local
    // variables that are simultaneously in scope).
    let cx = @mut Ctx {
        map: map,
        path: copy path,
        diag: diag,
    };
    let v = mk_ast_map_visitor();

    // methods get added to the AST map when their impl is visited.  Since we
    // don't decode and instantiate the impl, but just the method, we have to
    // add it to the table now:
    match *ii {
      ii_item(*) => { /* fallthrough */ }
      ii_foreign(i) => {
        cx.map.insert(i.id, node_foreign_item(i,
                                              AbiSet::Intrinsic(),
                                              i.vis,    // Wrong but OK
                                              @path));
      }
      ii_method(impl_did, m) => {
        map_method(impl_did, @path, m, cx);
      }
    }

    // visit the item / method contents and add those to the map:
    ii.accept(cx, v);
}

pub fn map_fn(
    fk: &visit::fn_kind,
    decl: &fn_decl,
    body: &blk,
    sp: codemap::span,
    id: node_id,
    cx: @mut Ctx,
    v: visit::vt<@mut Ctx>
) {
    for decl.inputs.each |a| {
        cx.map.insert(a.id, node_arg);
    }
    visit::visit_fn(fk, decl, body, sp, id, cx, v);
}

pub fn map_block(b: &blk, cx: @mut Ctx, v: visit::vt<@mut Ctx>) {
    cx.map.insert(b.node.id, node_block(/* FIXME (#2543) */ copy *b));
    visit::visit_block(b, cx, v);
}

pub fn map_pat(pat: @pat, cx: @mut Ctx, v: visit::vt<@mut Ctx>) {
    match pat.node {
        pat_ident(_, path, _) => {
            // Note: this is at least *potentially* a pattern...
            cx.map.insert(pat.id, node_local(ast_util::path_to_ident(path)));
        }
        _ => ()
    }

    visit::visit_pat(pat, cx, v);
}

pub fn map_method(impl_did: def_id, impl_path: @path,
                  m: @method, cx: @mut Ctx) {
    cx.map.insert(m.id, node_method(m, impl_did, impl_path));
    cx.map.insert(m.self_id, node_local(special_idents::self_));
}

pub fn map_item(i: @item, cx: @mut Ctx, v: visit::vt<@mut Ctx>) {
    let item_path = @/* FIXME (#2543) */ copy cx.path;
    cx.map.insert(i.id, node_item(i, item_path));
    match i.node {
        item_impl(_, _, _, ref ms) => {
            let impl_did = ast_util::local_def(i.id);
            for ms.each |m| {
                map_method(impl_did, extend(cx, i.ident), *m, cx);
            }
        }
        item_enum(ref enum_definition, _) => {
            for (*enum_definition).variants.each |v| {
                cx.map.insert(v.node.id, node_variant(
                    /* FIXME (#2543) */ copy *v, i,
                    extend(cx, i.ident)));
            }
        }
        item_foreign_mod(ref nm) => {
            for nm.items.each |nitem| {
                // Compute the visibility for this native item.
                let visibility = match nitem.vis {
                    public => public,
                    private => private,
                    inherited => i.vis
                };

                cx.map.insert(nitem.id,
                    node_foreign_item(
                        *nitem,
                        nm.abis,
                        visibility,
                        // FIXME (#2543)
                        if nm.sort == ast::named {
                            extend(cx, i.ident)
                        } else {
                            // Anonymous extern mods go in the parent scope
                            @copy cx.path
                        }
                    )
                );
            }
        }
        item_struct(struct_def, _) => {
            map_struct_def(
                struct_def,
                node_item(i, item_path),
                i.ident,
                cx,
                v
            );
        }
        item_trait(_, ref traits, ref methods) => {
            for traits.each |p| {
                cx.map.insert(p.ref_id, node_item(i, item_path));
            }
            for methods.each |tm| {
                let id = ast_util::trait_method_to_ty_method(tm).id;
                let d_id = ast_util::local_def(i.id);
                cx.map.insert(
                    id,
                    node_trait_method(@copy *tm, d_id, item_path)
                );
            }
        }
        _ => ()
    }

    match i.node {
        item_mod(_) | item_foreign_mod(_) => {
            cx.path.push(path_mod(i.ident));
        }
        _ => cx.path.push(path_name(i.ident))
    }
    visit::visit_item(i, cx, v);
    cx.path.pop();
}

pub fn map_struct_def(
    struct_def: @ast::struct_def,
    parent_node: ast_node,
    ident: ast::ident,
    cx: @mut Ctx,
    _v: visit::vt<@mut Ctx>
) {
    let p = extend(cx, ident);
    // If this is a tuple-like struct, register the constructor.
    match struct_def.ctor_id {
        None => {}
        Some(ctor_id) => {
            match parent_node {
                node_item(item, _) => {
                    cx.map.insert(ctor_id,
                                  node_struct_ctor(struct_def, item, p));
                }
                _ => fail!("struct def parent wasn't an item")
            }
        }
    }
}

pub fn map_expr(ex: @expr, cx: @mut Ctx, v: visit::vt<@mut Ctx>) {
    cx.map.insert(ex.id, node_expr(ex));
    // Expressions which are or might be calls:
    for ex.get_callee_id().each |callee_id| {
        cx.map.insert(*callee_id, node_callee_scope(ex));
    }
    visit::visit_expr(ex, cx, v);
}

pub fn map_stmt(stmt: @stmt, cx: @mut Ctx, v: visit::vt<@mut Ctx>) {
    cx.map.insert(stmt_id(stmt), node_stmt(stmt));
    visit::visit_stmt(stmt, cx, v);
}

pub fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str {
    match map.find(&id) {
      None => {
        fmt!("unknown node (id=%d)", id)
      }
      Some(&node_item(item, path)) => {
        let path_str = path_ident_to_str(path, item.ident, itr);
        let item_str = match item.node {
          item_const(*) => ~"const",
          item_fn(*) => ~"fn",
          item_mod(*) => ~"mod",
          item_foreign_mod(*) => ~"foreign mod",
          item_ty(*) => ~"ty",
          item_enum(*) => ~"enum",
          item_struct(*) => ~"struct",
          item_trait(*) => ~"trait",
          item_impl(*) => ~"impl",
          item_mac(*) => ~"macro"
        };
        fmt!("%s %s (id=%?)", item_str, path_str, id)
      }
      Some(&node_foreign_item(item, abi, _, path)) => {
        fmt!("foreign item %s with abi %? (id=%?)",
             path_ident_to_str(path, item.ident, itr), abi, id)
      }
      Some(&node_method(m, _, path)) => {
        fmt!("method %s in %s (id=%?)",
             *itr.get(m.ident), path_to_str(*path, itr), id)
      }
      Some(&node_trait_method(ref tm, _, path)) => {
        let m = ast_util::trait_method_to_ty_method(&**tm);
        fmt!("method %s in %s (id=%?)",
             *itr.get(m.ident), path_to_str(*path, itr), id)
      }
      Some(&node_variant(ref variant, _, path)) => {
        fmt!("variant %s in %s (id=%?)",
             *itr.get(variant.node.name), path_to_str(*path, itr), id)
      }
      Some(&node_expr(expr)) => {
        fmt!("expr %s (id=%?)", pprust::expr_to_str(expr, itr), id)
      }
      Some(&node_callee_scope(expr)) => {
        fmt!("callee_scope %s (id=%?)", pprust::expr_to_str(expr, itr), id)
      }
      Some(&node_stmt(stmt)) => {
        fmt!("stmt %s (id=%?)",
             pprust::stmt_to_str(stmt, itr), id)
      }
      Some(&node_arg) => {
        fmt!("arg (id=%?)", id)
      }
      Some(&node_local(ident)) => {
        fmt!("local (id=%?, name=%s)", id, *itr.get(ident))
      }
      Some(&node_block(_)) => {
        fmt!("block")
      }
      Some(&node_struct_ctor(*)) => {
        fmt!("struct_ctor")
      }
    }
}

pub fn node_item_query<Result>(items: map, id: node_id,
                               query: &fn(@item) -> Result,
                               error_msg: ~str) -> Result {
    match items.find(&id) {
        Some(&node_item(it, _)) => query(it),
        _ => fail!(error_msg)
    }
}
<commit_msg>auto merge of #6948 : huonw/rust/less-alloc, r=bstrie<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 core::prelude::*;

use abi::AbiSet;
use ast::*;
use ast;
use ast_util::{inlined_item_utils, stmt_id};
use ast_util;
use codemap;
use diagnostic::span_handler;
use parse::token::ident_interner;
use print::pprust;
use visit;
use syntax::parse::token::special_idents;

use core::cmp;
use core::hashmap::HashMap;
use core::str;
use core::vec;

pub enum path_elt {
    path_mod(ident),
    path_name(ident)
}

impl cmp::Eq for path_elt {
    fn eq(&self, other: &path_elt) -> bool {
        match (*self) {
            path_mod(e0a) => {
                match (*other) {
                    path_mod(e0b) => e0a == e0b,
                    _ => false
                }
            }
            path_name(e0a) => {
                match (*other) {
                    path_name(e0b) => e0a == e0b,
                    _ => false
                }
            }
        }
    }
    fn ne(&self, other: &path_elt) -> bool { !(*self).eq(other) }
}

pub type path = ~[path_elt];

pub fn path_to_str_with_sep(p: &[path_elt], sep: &str, itr: @ident_interner)
                         -> ~str {
    let strs = do p.map |e| {
        match *e {
          path_mod(s) => copy *itr.get(s),
          path_name(s) => copy *itr.get(s)
        }
    };
    str::connect(strs, sep)
}

pub fn path_ident_to_str(p: &path, i: ident, itr: @ident_interner) -> ~str {
    if vec::is_empty(*p) {
        //FIXME /* FIXME (#2543) */ copy *i
        copy *itr.get(i)
    } else {
        fmt!("%s::%s", path_to_str(*p, itr), *itr.get(i))
    }
}

pub fn path_to_str(p: &[path_elt], itr: @ident_interner) -> ~str {
    path_to_str_with_sep(p, "::", itr)
}

pub fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str {
    match pe {
        path_mod(s) => copy *itr.get(s),
        path_name(s) => copy *itr.get(s)
    }
}

pub enum ast_node {
    node_item(@item, @path),
    node_foreign_item(@foreign_item, AbiSet, visibility, @path),
    node_trait_method(@trait_method, def_id /* trait did */,
                      @path /* path to the trait */),
    node_method(@method, def_id /* impl did */, @path /* path to the impl */),
    node_variant(variant, @item, @path),
    node_expr(@expr),
    node_stmt(@stmt),
    node_arg,
    node_local(ident),
    node_block(blk),
    node_struct_ctor(@struct_def, @item, @path),
    node_callee_scope(@expr)
}

pub type map = @mut HashMap<node_id, ast_node>;

pub struct Ctx {
    map: map,
    path: path,
    diag: @span_handler,
}

pub type vt = visit::vt<@mut Ctx>;

pub fn extend(cx: @mut Ctx, elt: ident) -> @path {
    @(vec::append(copy cx.path, [path_name(elt)]))
}

pub fn mk_ast_map_visitor() -> vt {
    return visit::mk_vt(@visit::Visitor {
        visit_item: map_item,
        visit_expr: map_expr,
        visit_stmt: map_stmt,
        visit_fn: map_fn,
        visit_block: map_block,
        visit_pat: map_pat,
        .. *visit::default_visitor()
    });
}

pub fn map_crate(diag: @span_handler, c: @crate) -> map {
    let cx = @mut Ctx {
        map: @mut HashMap::new(),
        path: ~[],
        diag: diag,
    };
    visit::visit_crate(c, cx, mk_ast_map_visitor());
    cx.map
}

// Used for items loaded from external crate that are being inlined into this
// crate.  The `path` should be the path to the item but should not include
// the item itself.
pub fn map_decoded_item(diag: @span_handler,
                        map: map,
                        path: path,
                        ii: &inlined_item) {
    // I believe it is ok for the local IDs of inlined items from other crates
    // to overlap with the local ids from this crate, so just generate the ids
    // starting from 0.  (In particular, I think these ids are only used in
    // alias analysis, which we will not be running on the inlined items, and
    // even if we did I think it only needs an ordering between local
    // variables that are simultaneously in scope).
    let cx = @mut Ctx {
        map: map,
        path: copy path,
        diag: diag,
    };
    let v = mk_ast_map_visitor();

    // methods get added to the AST map when their impl is visited.  Since we
    // don't decode and instantiate the impl, but just the method, we have to
    // add it to the table now:
    match *ii {
      ii_item(*) => { /* fallthrough */ }
      ii_foreign(i) => {
        cx.map.insert(i.id, node_foreign_item(i,
                                              AbiSet::Intrinsic(),
                                              i.vis,    // Wrong but OK
                                              @path));
      }
      ii_method(impl_did, m) => {
        map_method(impl_did, @path, m, cx);
      }
    }

    // visit the item / method contents and add those to the map:
    ii.accept(cx, v);
}

pub fn map_fn(
    fk: &visit::fn_kind,
    decl: &fn_decl,
    body: &blk,
    sp: codemap::span,
    id: node_id,
    cx: @mut Ctx,
    v: visit::vt<@mut Ctx>
) {
    for decl.inputs.each |a| {
        cx.map.insert(a.id, node_arg);
    }
    visit::visit_fn(fk, decl, body, sp, id, cx, v);
}

pub fn map_block(b: &blk, cx: @mut Ctx, v: visit::vt<@mut Ctx>) {
    cx.map.insert(b.node.id, node_block(/* FIXME (#2543) */ copy *b));
    visit::visit_block(b, cx, v);
}

pub fn map_pat(pat: @pat, cx: @mut Ctx, v: visit::vt<@mut Ctx>) {
    match pat.node {
        pat_ident(_, path, _) => {
            // Note: this is at least *potentially* a pattern...
            cx.map.insert(pat.id, node_local(ast_util::path_to_ident(path)));
        }
        _ => ()
    }

    visit::visit_pat(pat, cx, v);
}

pub fn map_method(impl_did: def_id, impl_path: @path,
                  m: @method, cx: @mut Ctx) {
    cx.map.insert(m.id, node_method(m, impl_did, impl_path));
    cx.map.insert(m.self_id, node_local(special_idents::self_));
}

pub fn map_item(i: @item, cx: @mut Ctx, v: visit::vt<@mut Ctx>) {
    let item_path = @/* FIXME (#2543) */ copy cx.path;
    cx.map.insert(i.id, node_item(i, item_path));
    match i.node {
        item_impl(_, _, _, ref ms) => {
            let impl_did = ast_util::local_def(i.id);
            for ms.each |m| {
                map_method(impl_did, extend(cx, i.ident), *m, cx);
            }
        }
        item_enum(ref enum_definition, _) => {
            for (*enum_definition).variants.each |v| {
                cx.map.insert(v.node.id, node_variant(
                    /* FIXME (#2543) */ copy *v, i,
                    extend(cx, i.ident)));
            }
        }
        item_foreign_mod(ref nm) => {
            for nm.items.each |nitem| {
                // Compute the visibility for this native item.
                let visibility = match nitem.vis {
                    public => public,
                    private => private,
                    inherited => i.vis
                };

                cx.map.insert(nitem.id,
                    node_foreign_item(
                        *nitem,
                        nm.abis,
                        visibility,
                        // FIXME (#2543)
                        if nm.sort == ast::named {
                            extend(cx, i.ident)
                        } else {
                            // Anonymous extern mods go in the parent scope
                            @copy cx.path
                        }
                    )
                );
            }
        }
        item_struct(struct_def, _) => {
            map_struct_def(
                struct_def,
                node_item(i, item_path),
                i.ident,
                cx,
                v
            );
        }
        item_trait(_, ref traits, ref methods) => {
            for traits.each |p| {
                cx.map.insert(p.ref_id, node_item(i, item_path));
            }
            for methods.each |tm| {
                let id = ast_util::trait_method_to_ty_method(tm).id;
                let d_id = ast_util::local_def(i.id);
                cx.map.insert(
                    id,
                    node_trait_method(@copy *tm, d_id, item_path)
                );
            }
        }
        _ => ()
    }

    match i.node {
        item_mod(_) | item_foreign_mod(_) => {
            cx.path.push(path_mod(i.ident));
        }
        _ => cx.path.push(path_name(i.ident))
    }
    visit::visit_item(i, cx, v);
    cx.path.pop();
}

pub fn map_struct_def(
    struct_def: @ast::struct_def,
    parent_node: ast_node,
    ident: ast::ident,
    cx: @mut Ctx,
    _v: visit::vt<@mut Ctx>
) {
    let p = extend(cx, ident);
    // If this is a tuple-like struct, register the constructor.
    match struct_def.ctor_id {
        None => {}
        Some(ctor_id) => {
            match parent_node {
                node_item(item, _) => {
                    cx.map.insert(ctor_id,
                                  node_struct_ctor(struct_def, item, p));
                }
                _ => fail!("struct def parent wasn't an item")
            }
        }
    }
}

pub fn map_expr(ex: @expr, cx: @mut Ctx, v: visit::vt<@mut Ctx>) {
    cx.map.insert(ex.id, node_expr(ex));
    // Expressions which are or might be calls:
    for ex.get_callee_id().each |callee_id| {
        cx.map.insert(*callee_id, node_callee_scope(ex));
    }
    visit::visit_expr(ex, cx, v);
}

pub fn map_stmt(stmt: @stmt, cx: @mut Ctx, v: visit::vt<@mut Ctx>) {
    cx.map.insert(stmt_id(stmt), node_stmt(stmt));
    visit::visit_stmt(stmt, cx, v);
}

pub fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str {
    match map.find(&id) {
      None => {
        fmt!("unknown node (id=%d)", id)
      }
      Some(&node_item(item, path)) => {
        let path_str = path_ident_to_str(path, item.ident, itr);
        let item_str = match item.node {
          item_const(*) => ~"const",
          item_fn(*) => ~"fn",
          item_mod(*) => ~"mod",
          item_foreign_mod(*) => ~"foreign mod",
          item_ty(*) => ~"ty",
          item_enum(*) => ~"enum",
          item_struct(*) => ~"struct",
          item_trait(*) => ~"trait",
          item_impl(*) => ~"impl",
          item_mac(*) => ~"macro"
        };
        fmt!("%s %s (id=%?)", item_str, path_str, id)
      }
      Some(&node_foreign_item(item, abi, _, path)) => {
        fmt!("foreign item %s with abi %? (id=%?)",
             path_ident_to_str(path, item.ident, itr), abi, id)
      }
      Some(&node_method(m, _, path)) => {
        fmt!("method %s in %s (id=%?)",
             *itr.get(m.ident), path_to_str(*path, itr), id)
      }
      Some(&node_trait_method(ref tm, _, path)) => {
        let m = ast_util::trait_method_to_ty_method(&**tm);
        fmt!("method %s in %s (id=%?)",
             *itr.get(m.ident), path_to_str(*path, itr), id)
      }
      Some(&node_variant(ref variant, _, path)) => {
        fmt!("variant %s in %s (id=%?)",
             *itr.get(variant.node.name), path_to_str(*path, itr), id)
      }
      Some(&node_expr(expr)) => {
        fmt!("expr %s (id=%?)", pprust::expr_to_str(expr, itr), id)
      }
      Some(&node_callee_scope(expr)) => {
        fmt!("callee_scope %s (id=%?)", pprust::expr_to_str(expr, itr), id)
      }
      Some(&node_stmt(stmt)) => {
        fmt!("stmt %s (id=%?)",
             pprust::stmt_to_str(stmt, itr), id)
      }
      Some(&node_arg) => {
        fmt!("arg (id=%?)", id)
      }
      Some(&node_local(ident)) => {
        fmt!("local (id=%?, name=%s)", id, *itr.get(ident))
      }
      Some(&node_block(_)) => {
        fmt!("block")
      }
      Some(&node_struct_ctor(*)) => {
        fmt!("struct_ctor")
      }
    }
}

pub fn node_item_query<Result>(items: map, id: node_id,
                               query: &fn(@item) -> Result,
                               error_msg: ~str) -> Result {
    match items.find(&id) {
        Some(&node_item(it, _)) => query(it),
        _ => fail!(error_msg)
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 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.

/*
 * The compiler code necessary to support the env! extension.  Eventually this
 * should all get sucked into either the compiler syntax extension plugin
 * interface.
 */

use ast;
use codemap::Span;
use ext::base::*;
use ext::base;
use ext::build::AstBuilder;
use parse::token;

use std::env;
use std::os;
use std::ops::Deref;

pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                              -> Box<base::MacResult+'cx> {
    let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
        None => return DummyResult::expr(sp),
        Some(v) => v
    };

    let e = match env::var_string(&var[]) {
      Err(..) => {
          cx.expr_path(cx.path_all(sp,
                                   true,
                                   vec!(cx.ident_of("std"),
                                        cx.ident_of("option"),
                                        cx.ident_of("Option"),
                                        cx.ident_of("None")),
                                   Vec::new(),
                                   vec!(cx.ty_rptr(sp,
                                                   cx.ty_ident(sp,
                                                        cx.ident_of("str")),
                                                   Some(cx.lifetime(sp,
                                                        cx.ident_of(
                                                            "'static").name)),
                                                   ast::MutImmutable)),
                                   Vec::new()))
      }
      Ok(s) => {
          cx.expr_call_global(sp,
                              vec!(cx.ident_of("std"),
                                   cx.ident_of("option"),
                                   cx.ident_of("Option"),
                                   cx.ident_of("Some")),
                              vec!(cx.expr_str(sp,
                                               token::intern_and_get_ident(
                                          &s[]))))
      }
    };
    MacExpr::new(e)
}

pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                       -> Box<base::MacResult+'cx> {
    let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
        Some(ref exprs) if exprs.len() == 0 => {
            cx.span_err(sp, "env! takes 1 or 2 arguments");
            return DummyResult::expr(sp);
        }
        None => return DummyResult::expr(sp),
        Some(exprs) => exprs.into_iter()
    };

    let var = match expr_to_string(cx,
                                exprs.next().unwrap(),
                                "expected string literal") {
        None => return DummyResult::expr(sp),
        Some((v, _style)) => v
    };
    let msg = match exprs.next() {
        None => {
            token::intern_and_get_ident(&format!("environment variable `{}` \
                                                 not defined",
                                                var)[])
        }
        Some(second) => {
            match expr_to_string(cx, second, "expected string literal") {
                None => return DummyResult::expr(sp),
                Some((s, _style)) => s
            }
        }
    };

    match exprs.next() {
        None => {}
        Some(_) => {
            cx.span_err(sp, "env! takes 1 or 2 arguments");
            return DummyResult::expr(sp);
        }
    }

    let e = match os::getenv(var.deref()) {
        None => {
            cx.span_err(sp, msg.deref());
            cx.expr_usize(sp, 0)
        }
        Ok(s) => cx.expr_str(sp, token::intern_and_get_ident(&s[]))
    };
    MacExpr::new(e)
}
<commit_msg>Update HEAD:master<commit_after>// Copyright 2012-2013 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.

/*
 * The compiler code necessary to support the env! extension.  Eventually this
 * should all get sucked into either the compiler syntax extension plugin
 * interface.
 */

use ast;
use codemap::Span;
use ext::base::*;
use ext::base;
use ext::build::AstBuilder;
use parse::token;

use std::env;
use std::os;
use std::ops::Deref;

pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                              -> Box<base::MacResult+'cx> {
    let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
        None => return DummyResult::expr(sp),
        Some(v) => v
    };

    let e = match env::var_string(&var[]) {
      Err(..) => {
          cx.expr_path(cx.path_all(sp,
                                   true,
                                   vec!(cx.ident_of("std"),
                                        cx.ident_of("option"),
                                        cx.ident_of("Option"),
                                        cx.ident_of("None")),
                                   Vec::new(),
                                   vec!(cx.ty_rptr(sp,
                                                   cx.ty_ident(sp,
                                                        cx.ident_of("str")),
                                                   Some(cx.lifetime(sp,
                                                        cx.ident_of(
                                                            "'static").name)),
                                                   ast::MutImmutable)),
                                   Vec::new()))
      }
      Ok(s) => {
          cx.expr_call_global(sp,
                              vec!(cx.ident_of("std"),
                                   cx.ident_of("option"),
                                   cx.ident_of("Option"),
                                   cx.ident_of("Some")),
                              vec!(cx.expr_str(sp,
                                               token::intern_and_get_ident(
                                          &s[]))))
      }
    };
    MacExpr::new(e)
}

pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                       -> Box<base::MacResult+'cx> {
    let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
        Some(ref exprs) if exprs.len() == 0 => {
            cx.span_err(sp, "env! takes 1 or 2 arguments");
            return DummyResult::expr(sp);
        }
        None => return DummyResult::expr(sp),
        Some(exprs) => exprs.into_iter()
    };

    let var = match expr_to_string(cx,
                                exprs.next().unwrap(),
                                "expected string literal") {
        None => return DummyResult::expr(sp),
        Some((v, _style)) => v
    };
    let msg = match exprs.next() {
        None => {
            token::intern_and_get_ident(&format!("environment variable `{}` \
                                                 not defined",
                                                var)[])
        }
        Some(second) => {
            match expr_to_string(cx, second, "expected string literal") {
                None => return DummyResult::expr(sp),
                Some((s, _style)) => s
            }
        }
    };

    match exprs.next() {
        None => {}
        Some(_) => {
            cx.span_err(sp, "env! takes 1 or 2 arguments");
            return DummyResult::expr(sp);
        }
    }

    let e = match os::getenv(var.deref()) {
        None => {
            cx.span_err(sp, msg.deref());
            cx.expr_usize(sp, 0)
        }
        Some(s) => cx.expr_str(sp, token::intern_and_get_ident(&s[]))
    };
    MacExpr::new(e)
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex32, Complex64};
use matrix::{BlasMatrix};
use matrix_vector;
use pointer::CPtr;
use scalar::Scalar;
use vector::BlasVector;

pub trait Gemv {
    fn gemv(alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

macro_rules! gemv_impl(
    ($t: ty, $gemv_fn: ident) => (
        impl Gemv for $t {
            fn gemv(alpha: $t, a: &BlasMatrix<$t>, x: &BlasVector<$t>, beta: $t, y: &mut BlasVector<$t>){
                unsafe {
                    matrix_vector::ll::$gemv_fn(a.order(), a.transpose(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        (&beta).as_const(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

gemv_impl!(f32,       cblas_sgemv)
gemv_impl!(f64,       cblas_dgemv)
gemv_impl!(Complex32, cblas_cgemv)
gemv_impl!(Complex64, cblas_zgemv)
<commit_msg>Add Symv and Hemv traits<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex32, Complex64};
use attribute::Symmetry;
use matrix::{BlasMatrix};
use matrix_vector;
use pointer::CPtr;
use scalar::Scalar;
use vector::BlasVector;

pub trait Gemv {
    fn gemv(alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

macro_rules! gemv_impl(
    ($t: ty, $gemv_fn: ident) => (
        impl Gemv for $t {
            fn gemv(alpha: $t, a: &BlasMatrix<$t>, x: &BlasVector<$t>, beta: $t, y: &mut BlasVector<$t>){
                unsafe {
                    matrix_vector::ll::$gemv_fn(a.order(), a.transpose(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        (&beta).as_const(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

gemv_impl!(f32,       cblas_sgemv)
gemv_impl!(f64,       cblas_dgemv)
gemv_impl!(Complex32, cblas_cgemv)
gemv_impl!(Complex64, cblas_zgemv)

pub trait Symv {
    fn symv(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

pub trait Hemv {
    fn hemv(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

macro_rules! symv_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $symv_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(symmetry: Symmetry, alpha: $t, a: &BlasMatrix<$t>, x: &BlasVector<$t>, beta: $t, y: &mut BlasVector<$t>){
                unsafe {
                    matrix_vector::ll::$symv_fn(a.order(), symmetry,
                        a.rows(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        (&beta).as_const(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

symv_impl!(Symv, symv, f32,       cblas_ssymv)
symv_impl!(Symv, symv, f64,       cblas_dsymv)
symv_impl!(Symv, symv, Complex32, cblas_csymv)
symv_impl!(Symv, symv, Complex64, cblas_zsymv)

symv_impl!(Hemv, hemv, Complex32, cblas_chemv)
symv_impl!(Hemv, hemv, Complex64, cblas_zhemv)
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex32, Complex64};
use attribute::Symmetry;
use matrix::{BlasMatrix};
use matrix_vector;
use pointer::CPtr;
use scalar::Scalar;
use vector::BlasVector;

pub trait Gemv {
    fn gemv(alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

macro_rules! gemv_impl(
    ($t: ty, $gemv_fn: ident) => (
        impl Gemv for $t {
            fn gemv(alpha: $t, a: &BlasMatrix<$t>, x: &BlasVector<$t>, beta: $t, y: &mut BlasVector<$t>){
                unsafe {
                    matrix_vector::ll::$gemv_fn(a.order(), a.transpose(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        (&beta).as_const(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

gemv_impl!(f32,       cblas_sgemv)
gemv_impl!(f64,       cblas_dgemv)
gemv_impl!(Complex32, cblas_cgemv)
gemv_impl!(Complex64, cblas_zgemv)

pub trait Symv {
    fn symv(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

pub trait Hemv {
    fn hemv(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

macro_rules! symv_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $symv_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(symmetry: Symmetry, alpha: $t, a: &BlasMatrix<$t>, x: &BlasVector<$t>, beta: $t, y: &mut BlasVector<$t>){
                unsafe {
                    matrix_vector::ll::$symv_fn(a.order(), symmetry,
                        a.rows(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        (&beta).as_const(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

symv_impl!(Symv, symv, f32,       cblas_ssymv)
symv_impl!(Symv, symv, f64,       cblas_dsymv)
symv_impl!(Symv, symv, Complex32, cblas_csymv)
symv_impl!(Symv, symv, Complex64, cblas_zsymv)

symv_impl!(Hemv, hemv, Complex32, cblas_chemv)
symv_impl!(Hemv, hemv, Complex64, cblas_zhemv)
<commit_msg>Add Ger and Gerc traits<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex32, Complex64};
use attribute::Symmetry;
use matrix::{BlasMatrix};
use matrix_vector;
use pointer::CPtr;
use scalar::Scalar;
use vector::BlasVector;

pub trait Gemv {
    fn gemv(alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

macro_rules! gemv_impl(
    ($t: ty, $gemv_fn: ident) => (
        impl Gemv for $t {
            fn gemv(alpha: $t, a: &BlasMatrix<$t>, x: &BlasVector<$t>, beta: $t, y: &mut BlasVector<$t>){
                unsafe {
                    matrix_vector::ll::$gemv_fn(a.order(), a.transpose(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        (&beta).as_const(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

gemv_impl!(f32,       cblas_sgemv)
gemv_impl!(f64,       cblas_dgemv)
gemv_impl!(Complex32, cblas_cgemv)
gemv_impl!(Complex64, cblas_zgemv)

pub trait Symv {
    fn symv(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

pub trait Hemv {
    fn hemv(symmetry: Symmetry, alpha: Self, a: &BlasMatrix<Self>, x: &BlasVector<Self>, beta: Self, y: &mut BlasVector<Self>);
}

macro_rules! symv_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $symv_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(symmetry: Symmetry, alpha: $t, a: &BlasMatrix<$t>, x: &BlasVector<$t>, beta: $t, y: &mut BlasVector<$t>){
                unsafe {
                    matrix_vector::ll::$symv_fn(a.order(), symmetry,
                        a.rows(),
                        (&alpha).as_const(),
                        a.as_ptr().as_c_ptr(), a.lead_dim(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        (&beta).as_const(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

symv_impl!(Symv, symv, f32,       cblas_ssymv)
symv_impl!(Symv, symv, f64,       cblas_dsymv)
symv_impl!(Symv, symv, Complex32, cblas_csymv)
symv_impl!(Symv, symv, Complex64, cblas_zsymv)

symv_impl!(Hemv, hemv, Complex32, cblas_chemv)
symv_impl!(Hemv, hemv, Complex64, cblas_zhemv)

pub trait Ger {
    fn ger(alpha: Self, x: &BlasVector<Self>, y: &BlasVector<Self>, a: &mut BlasMatrix<Self>);
}

pub trait Gerc {
    fn gerc(alpha: Self, x: &BlasVector<Self>, y: &BlasVector<Self>, a: &mut BlasMatrix<Self>);
}

macro_rules! ger_impl(
    ($trait_name: ident, $fn_name: ident, $t: ty, $ger_fn: ident) => (
        impl $trait_name for $t {
            fn $fn_name(alpha: $t, x: &BlasVector<$t>, y: &BlasVector<$t>, a: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix_vector::ll::$ger_fn(a.order(),
                        a.rows(), a.cols(),
                        (&alpha).as_const(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        y.as_ptr().as_c_ptr(), y.inc(),
                        a.as_mut_ptr().as_c_ptr(), a.lead_dim());
                }
            }
        }
    );
)

ger_impl!(Ger, ger, f32,       cblas_sger)
ger_impl!(Ger, ger, f64,       cblas_dger)
ger_impl!(Ger, ger, Complex32, cblas_cgeru)
ger_impl!(Ger, ger, Complex64, cblas_zgeru)

ger_impl!(Gerc, gerc, Complex32, cblas_cgerc)
ger_impl!(Gerc, gerc, Complex64, cblas_zgerc)
<|endoftext|>


<commit_before>import std::test;
import std::str;
import std::option;
import std::either;
import std::vec;

#[test]
fn do_not_run_ignored_tests() {
    /*let ran = @mutable false;
    let f = bind fn (ran: @mutable bool) { *ran = true; }(ran);

    let desc = {name: "whatever", fn: f, ignore: true};

    test::run_test(desc, test::default_test_to_task);

    assert (*ran == false);*/
}

#[test]
fn ignored_tests_result_in_ignored() {
    /*fn f() { }
    let desc = {name: "whatever", fn: f, ignore: true};
    let res = test::run_test(desc, test::default_test_to_task).wait();
    assert (res == test::tr_ignored);*/
}

#[test]
fn first_free_arg_should_be_a_filter() {
    let args = ["progname", "filter"];
    check (vec::is_not_empty(args));
    let opts = alt test::parse_opts(args) { either::left(o) { o } };
    assert (str::eq("filter", option::get(opts.filter)));
}

#[test]
fn parse_ignored_flag() {
    let args = ["progname", "filter", "--ignored"];
    check (vec::is_not_empty(args));
    let opts = alt test::parse_opts(args) { either::left(o) { o } };
    assert (opts.run_ignored);
}

#[test]
fn filter_for_ignored_option() {
    // When we run ignored tests the test filter should filter out all the
    // unignored tests and flip the ignore flag on the rest to false

    let opts = {filter: option::none, run_ignored: true};
    let tests =
        [{name: "1", fn: fn () { }, ignore: true},
         {name: "2", fn: fn () { }, ignore: false}];
    let filtered = test::filter_tests(opts, tests);

    assert (vec::len(filtered) == 1u);
    assert (filtered[0].name == "1");
    assert (filtered[0].ignore == false);
}

#[test]
fn sort_tests() {
    let opts = {filter: option::none, run_ignored: false};

    let names =
        ["sha1::test", "int::test_to_str", "int::test_pow",
         "test::do_not_run_ignored_tests",
         "test::ignored_tests_result_in_ignored",
         "test::first_free_arg_should_be_a_filter",
         "test::parse_ignored_flag", "test::filter_for_ignored_option",
         "test::sort_tests"];
    let tests =
        {
            let testfn = fn () { };
            let tests = [];
            for name: str in names {
                let test = {name: name, fn: testfn, ignore: false};
                tests += [test];
            }
            tests
        };
    let filtered = test::filter_tests(opts, tests);

    let expected =
        ["int::test_pow", "int::test_to_str", "sha1::test",
         "test::do_not_run_ignored_tests", "test::filter_for_ignored_option",
         "test::first_free_arg_should_be_a_filter",
         "test::ignored_tests_result_in_ignored", "test::parse_ignored_flag",
         "test::sort_tests"];

    check (vec::same_length(expected, filtered));
    let pairs = vec::zip(expected, filtered);

    for (a, b) in pairs { assert (a == b.name); }
}

// 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 .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Restore broken tests in stdtest::test<commit_after>import std::test;
import std::str;
import std::option;
import std::either;
import std::vec;

#[test]
fn do_not_run_ignored_tests() {
    fn f() { fail; }
    let desc = {name: "whatever", fn: f, ignore: true};
    let future = test::run_test(desc, test::default_test_to_task);
    let result = future.wait();
    assert result != test::tr_ok;
}

#[test]
fn ignored_tests_result_in_ignored() {
    fn f() { }
    let desc = {name: "whatever", fn: f, ignore: true};
    let res = test::run_test(desc, test::default_test_to_task).wait();
    assert (res == test::tr_ignored);
}

#[test]
fn first_free_arg_should_be_a_filter() {
    let args = ["progname", "filter"];
    check (vec::is_not_empty(args));
    let opts = alt test::parse_opts(args) { either::left(o) { o } };
    assert (str::eq("filter", option::get(opts.filter)));
}

#[test]
fn parse_ignored_flag() {
    let args = ["progname", "filter", "--ignored"];
    check (vec::is_not_empty(args));
    let opts = alt test::parse_opts(args) { either::left(o) { o } };
    assert (opts.run_ignored);
}

#[test]
fn filter_for_ignored_option() {
    // When we run ignored tests the test filter should filter out all the
    // unignored tests and flip the ignore flag on the rest to false

    let opts = {filter: option::none, run_ignored: true};
    let tests =
        [{name: "1", fn: fn () { }, ignore: true},
         {name: "2", fn: fn () { }, ignore: false}];
    let filtered = test::filter_tests(opts, tests);

    assert (vec::len(filtered) == 1u);
    assert (filtered[0].name == "1");
    assert (filtered[0].ignore == false);
}

#[test]
fn sort_tests() {
    let opts = {filter: option::none, run_ignored: false};

    let names =
        ["sha1::test", "int::test_to_str", "int::test_pow",
         "test::do_not_run_ignored_tests",
         "test::ignored_tests_result_in_ignored",
         "test::first_free_arg_should_be_a_filter",
         "test::parse_ignored_flag", "test::filter_for_ignored_option",
         "test::sort_tests"];
    let tests =
        {
            let testfn = fn () { };
            let tests = [];
            for name: str in names {
                let test = {name: name, fn: testfn, ignore: false};
                tests += [test];
            }
            tests
        };
    let filtered = test::filter_tests(opts, tests);

    let expected =
        ["int::test_pow", "int::test_to_str", "sha1::test",
         "test::do_not_run_ignored_tests", "test::filter_for_ignored_option",
         "test::first_free_arg_should_be_a_filter",
         "test::ignored_tests_result_in_ignored", "test::parse_ignored_flag",
         "test::sort_tests"];

    check (vec::same_length(expected, filtered));
    let pairs = vec::zip(expected, filtered);

    for (a, b) in pairs { assert (a == b.name); }
}

// 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 .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>extern crate combine;
extern crate combine_language;
extern crate mnemosyne as core;

use combine::*;
use combine_language::{ LanguageEnv
                      , LanguageDef
                      , Identifier
                      };
use combine::primitives::{ Stream
                         , Positioner
                         , SourcePosition
                         };

use core::semantic::*;
use core::semantic::annotations::{ Annotated
                                 , UnscopedState
                                 , Unscoped
                                 };
use core::semantic::types::*;
use core::semantic::ast::*;
use core::position::*;

use std::rc::Rc;

type ParseFn<'a, I, T> = fn (&MnEnv<'a, I>, State<I>) -> ParseResult<T, I>;

type U = UnscopedState;

/// Wraps a parsing function with a language definition environment.
///
/// TODO: this could probably push identifiers to the symbol table here?
#[derive(Copy)]
struct MnParser<'a: 'b, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b {
        env: &'b MnEnv<'a, I>
      , parser: ParseFn<'a, I, T>
}

impl<'a, 'b, I, T> Clone for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    fn clone(&self) -> Self {
        MnParser { env: self.env , parser: self.parser }
    }
}

impl<'a, 'b, I, T> Parser for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    type Input = I;
    type Output = T;

    fn parse_state(&mut self, input: State<I>) -> ParseResult<T, I> {
        (self.parser)(self.env, input)
    }

}

struct MnEnv<'a, I>
where I: Stream<Item = char>
    , I::Item: Positioner<Position = SourcePosition> {
    env: LanguageEnv<'a, I>
}

impl <'a, I> std::ops::Deref for MnEnv<'a, I>
where I: Stream<Item=char> {
    type Target = LanguageEnv<'a, I>;
    fn deref(&self) -> &LanguageEnv<'a, I> { &self.env }
}

impl<'a, 'b, I> MnEnv<'a, I>
where I: Stream<Item=char>
    , I::Item: Positioner<Position = SourcePosition>
    , I::Range: 'b {

    /// Wrap a function into a MnParser with this environment
    fn parser<T>(&'b self, parser: ParseFn<'a, I, T>)
                -> MnParser<'a, 'b, I, T> {
        MnParser { env: self, parser: parser }
    }

    fn parse_def(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        let function_form
            = self.name()
                  .and(self.function())
                  .map(|(name, fun)| DefForm::Function { name: name
                                                       , fun: fun });
        let top_level
            = self.name()
                  .and(self.type_annotation())
                  .and(self.expr())
                  .map(|((name, ty), body)|
                    DefForm::TopLevel { name: name
                                      , annot: ty
                                      , value: Rc::new(body) });
        self.reserved("defn").or(self.reserved("define"))
            .with(function_form.or(top_level))
            .map(Form::Define)
            .parse_state(input)
    }

    fn parse_if(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        unimplemented!()
    }

    fn parse_lambda(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        unimplemented!()
    }

    fn parse_function(&self, input: State<I>) -> ParseResult<Function<'a, U>, I> {
        unimplemented!()
    }

    fn parse_primitive_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.reserved("int")
                     .with(value(Primitive::IntSize))
               , self.reserved("uint")
                     .with(value(Primitive::IntSize))
               , self.reserved("float")
                     .with(value(Primitive::Float))
               , self.reserved("double")
                     .with(value(Primitive::Double))
               , self.reserved("bool")
                     .with(value(Primitive::Bool))
               ])
               .map(|primitive| Type::Prim(primitive))
               .parse_state(input)
    }

    fn raw_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('*').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Raw(Rc::new(t))))
                 .parse_state(input)
    }

    fn unique_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('@').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Unique(Rc::new(t))))
                 .parse_state(input)
    }

    fn borrow_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('&').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Borrowed(Rc::new(t))))
                 .parse_state(input)
    }
    fn parse_type(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.parser(MnEnv::parse_primitive_ty)
               , self.parser(MnEnv::raw_ptr_ty)
               , self.parser(MnEnv::unique_ptr_ty)
               , self.parser(MnEnv::borrow_ptr_ty)
               ])
            .parse_state(input)
    }

    fn parse_binding(&self, input: State<I>)
                    -> ParseResult<Unscoped<'a, Binding<'a, U>>, I> {
        let pos = input.position.clone();
        self.parser(MnEnv::parse_name)
            .and(self.type_annotation())
            .and(self.expr())
            .map(|((name, typ), value)|
                Annotated::new( Binding { name: name
                                        , typ: typ
                                        , value: Rc::new(value)
                                        }
                               , Position::from(pos)
                           ))
            .parse_state(input)
    }

    fn parse_let(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {

        let binding_form =
            self.reserved("let")
                .with(many(self.parens(self.binding())))
                .and(many(self.expr()))
                .map(|(bindings, body)| LetForm::Let { bindings: bindings
                                                     , body: body });

        choice([ binding_form ])
            .map(Form::Let)
            .parse_state(input)
    }

    fn parse_name (&self, input: State<I>) -> ParseResult<Ident, I> {
        let position = input.position.clone();
        self.env.identifier::<'b>()
            .map(|name| Positional { pos: Position::from(position)
                                   , value: name })
            .parse_state(input)
    }

    fn parse_call(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.name()
            .and(many(self.expr()))
            .map(|(name, args)| Form::Call { fun: name, body: args })
            .parse_state(input)
    }

    fn parse_expr(&self, input: State<I>) -> ParseResult<Expr<'a, U>, I> {
        let pos = Position::from(input.position.clone());
        self.env
            .parens(choice([ self.def()
                           , self.if_form()
                           , self.lambda()
                           , self.let_form()
                           , self.call()
                           ]))
            .map(|f| Annotated::new(f, pos) )
            .parse_state(input)
    }

    fn expr(&'b self) -> MnParser<'a, 'b, I, Expr<'a, U>> {
        self.parser(MnEnv::parse_expr)
    }

    fn def(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_def)
    }

    fn if_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_if)
    }

    fn let_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_let)
    }

    fn lambda(&'b self)-> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_lambda)
    }

    fn call(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_call)
    }

    fn name(&'b self) -> MnParser<'a, 'b, I, Ident> {
        self.parser(MnEnv::parse_name)
    }

    fn binding(&'b self)
              -> MnParser< 'a, 'b, I, Unscoped<'a, Binding<'a, U>>> {
        self.parser(MnEnv::parse_binding)
    }

    fn type_annotation(&'b self) -> MnParser<'a, 'b, I, types::Type> {
        self.parser(MnEnv::parse_type)
    }

    fn function(&'b self) -> MnParser<'a, 'b, I, Function<'a, U>> {
        self.parser(MnEnv::parse_function)
    }

}
pub fn parse_module<N: ?Sized>(code: &str) -> Result<Vec<N>, ParseError<&str>>
where N: ASTNode + Sized {
    let alpha_ext = "+-*/<=>!?:$%_~^";
    let ops = "+-*/|=<>";
    let env = LanguageEnv::new(LanguageDef {
        ident: Identifier {
            start: letter().or(satisfy(|c| alpha_ext.contains(c)))
          , rest: alpha_num().or(satisfy(|c| alpha_ext.contains(c)))
          , reserved: [ "and"               , "begin"
                      , "case"              , "cond"
                      , "data"              , "define"
                      , "defn"              , "delay"
                      , "do"                , "else"
                      , "if"                , "lambda"
                      , "let"               , "let*"
                      , "letrec"            , "or"
                      , "quasiquote"        , "quote"
                      , "set!"              , "unquote"
                      , "unquote-splicing"
                      , "i8"                , "u8"
                      , "i16"               , "u16"
                      , "i32"               , "u32"         , "f32"
                      , "i64"               , "u64"         , "f64"
                      , "int"               , "uint"        , "float"
                      , "bool"                              , "double"
                      ].iter().map(|x| (*x).into()).collect()
        }
      , op: Identifier {
            start: satisfy(|c| ops.contains(c))
          , rest:  satisfy(|c| ops.contains(c))
          , reserved: [ "=>", "->", "\\", "|"].iter().map(|x| (*x).into())
                                                     .collect()
        }
      , comment_line: string(";").map(|_| ())
      , comment_start: string("#|").map(|_| ())
      , comment_end: string("|#").map(|_| ())
    });
    let env = MnEnv { env: env };

    env.white_space()
       .parse(code);

    unimplemented!()
}
<commit_msg>Parser now handles a bunch more numeric types<commit_after>extern crate combine;
extern crate combine_language;
extern crate mnemosyne as core;

use combine::*;
use combine_language::{ LanguageEnv
                      , LanguageDef
                      , Identifier
                      };
use combine::primitives::{ Stream
                         , Positioner
                         , SourcePosition
                         };

use core::semantic::*;
use core::semantic::annotations::{ Annotated
                                 , UnscopedState
                                 , Unscoped
                                 };
use core::semantic::types::*;
use core::semantic::ast::*;
use core::position::*;

use std::rc::Rc;

type ParseFn<'a, I, T> = fn (&MnEnv<'a, I>, State<I>) -> ParseResult<T, I>;

type U = UnscopedState;

/// Wraps a parsing function with a language definition environment.
///
/// TODO: this could probably push identifiers to the symbol table here?
#[derive(Copy)]
struct MnParser<'a: 'b, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b {
        env: &'b MnEnv<'a, I>
      , parser: ParseFn<'a, I, T>
}

impl<'a, 'b, I, T> Clone for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    fn clone(&self) -> Self {
        MnParser { env: self.env , parser: self.parser }
    }
}

impl<'a, 'b, I, T> Parser for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    type Input = I;
    type Output = T;

    fn parse_state(&mut self, input: State<I>) -> ParseResult<T, I> {
        (self.parser)(self.env, input)
    }

}

struct MnEnv<'a, I>
where I: Stream<Item = char>
    , I::Item: Positioner<Position = SourcePosition> {
    env: LanguageEnv<'a, I>
}

impl <'a, I> std::ops::Deref for MnEnv<'a, I>
where I: Stream<Item=char> {
    type Target = LanguageEnv<'a, I>;
    fn deref(&self) -> &LanguageEnv<'a, I> { &self.env }
}

impl<'a, 'b, I> MnEnv<'a, I>
where I: Stream<Item=char>
    , I::Item: Positioner<Position = SourcePosition>
    , I::Range: 'b {

    /// Wrap a function into a MnParser with this environment
    fn parser<T>(&'b self, parser: ParseFn<'a, I, T>)
                -> MnParser<'a, 'b, I, T> {
        MnParser { env: self, parser: parser }
    }

    fn parse_def(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        let function_form
            = self.name()
                  .and(self.function())
                  .map(|(name, fun)| DefForm::Function { name: name
                                                       , fun: fun });
        let top_level
            = self.name()
                  .and(self.type_annotation())
                  .and(self.expr())
                  .map(|((name, ty), body)|
                    DefForm::TopLevel { name: name
                                      , annot: ty
                                      , value: Rc::new(body) });
        self.reserved("defn").or(self.reserved("define"))
            .with(function_form.or(top_level))
            .map(Form::Define)
            .parse_state(input)
    }

    fn parse_if(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        unimplemented!()
    }

    fn parse_lambda(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        unimplemented!()
    }

    fn parse_function(&self, input: State<I>) -> ParseResult<Function<'a, U>, I> {
        unimplemented!()
    }

    fn parse_primitive_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.reserved("int")
                     .with(value(Primitive::IntSize))
               , self.reserved("uint")
                     .with(value(Primitive::IntSize))
               , self.reserved("float")
                     .with(value(Primitive::Float))
               , self.reserved("double")
                     .with(value(Primitive::Double))
               , self.reserved("bool")
                     .with(value(Primitive::Bool))
               , self.reserved("i8")
                     .with(value(Primitive::Int(Int::Int8)))
               , self.reserved("i16")
                     .with(value(Primitive::Int(Int::Int16)))
               , self.reserved("i32")
                    .with(value(Primitive::Int(Int::Int32)))
               , self.reserved("i64")
                     .with(value(Primitive::Int(Int::Int64)))
              , self.reserved("u8")
                    .with(value(Primitive::Uint(Int::Int8)))
              , self.reserved("u16")
                    .with(value(Primitive::Uint(Int::Int16)))
              , self.reserved("u32")
                    .with(value(Primitive::Uint(Int::Int32)))
              , self.reserved("u64")
                    .with(value(Primitive::Uint(Int::Int64)))
               ])
               .map(|primitive| Type::Prim(primitive))
               .parse_state(input)
    }

    fn raw_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('*').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Raw(Rc::new(t))))
                 .parse_state(input)
    }

    fn unique_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('@').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Unique(Rc::new(t))))
                 .parse_state(input)
    }

    fn borrow_ptr_ty(&self, input: State<I>) -> ParseResult<Type, I> {
        char('&').with(self.type_annotation())
                 .map(|t| Type::Ref(Reference::Borrowed(Rc::new(t))))
                 .parse_state(input)
    }
    fn parse_type(&self, input: State<I>) -> ParseResult<Type, I> {
        choice([ self.parser(MnEnv::parse_primitive_ty)
               , self.parser(MnEnv::raw_ptr_ty)
               , self.parser(MnEnv::unique_ptr_ty)
               , self.parser(MnEnv::borrow_ptr_ty)
               ])
            .parse_state(input)
    }

    fn parse_binding(&self, input: State<I>)
                    -> ParseResult<Unscoped<'a, Binding<'a, U>>, I> {
        let pos = input.position.clone();
        self.parser(MnEnv::parse_name)
            .and(self.type_annotation())
            .and(self.expr())
            .map(|((name, typ), value)|
                Annotated::new( Binding { name: name
                                        , typ: typ
                                        , value: Rc::new(value)
                                        }
                               , Position::from(pos)
                           ))
            .parse_state(input)
    }

    fn parse_let(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {

        let binding_form =
            self.reserved("let")
                .with(many(self.parens(self.binding())))
                .and(many(self.expr()))
                .map(|(bindings, body)| LetForm::Let { bindings: bindings
                                                     , body: body });

        choice([ binding_form ])
            .map(Form::Let)
            .parse_state(input)
    }

    fn parse_name (&self, input: State<I>) -> ParseResult<Ident, I> {
        let position = input.position.clone();
        self.env.identifier::<'b>()
            .map(|name| Positional { pos: Position::from(position)
                                   , value: name })
            .parse_state(input)
    }

    fn parse_call(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
        self.name()
            .and(many(self.expr()))
            .map(|(name, args)| Form::Call { fun: name, body: args })
            .parse_state(input)
    }

    fn parse_expr(&self, input: State<I>) -> ParseResult<Expr<'a, U>, I> {
        let pos = Position::from(input.position.clone());
        self.env
            .parens(choice([ self.def()
                           , self.if_form()
                           , self.lambda()
                           , self.let_form()
                           , self.call()
                           ]))
            .map(|f| Annotated::new(f, pos) )
            .parse_state(input)
    }

    fn expr(&'b self) -> MnParser<'a, 'b, I, Expr<'a, U>> {
        self.parser(MnEnv::parse_expr)
    }

    fn def(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_def)
    }

    fn if_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_if)
    }

    fn let_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_let)
    }

    fn lambda(&'b self)-> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_lambda)
    }

    fn call(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
        self.parser(MnEnv::parse_call)
    }

    fn name(&'b self) -> MnParser<'a, 'b, I, Ident> {
        self.parser(MnEnv::parse_name)
    }

    fn binding(&'b self)
              -> MnParser< 'a, 'b, I, Unscoped<'a, Binding<'a, U>>> {
        self.parser(MnEnv::parse_binding)
    }

    fn type_annotation(&'b self) -> MnParser<'a, 'b, I, types::Type> {
        self.parser(MnEnv::parse_type)
    }

    fn function(&'b self) -> MnParser<'a, 'b, I, Function<'a, U>> {
        self.parser(MnEnv::parse_function)
    }

}
pub fn parse_module<N: ?Sized>(code: &str) -> Result<Vec<N>, ParseError<&str>>
where N: ASTNode + Sized {
    let alpha_ext = "+-*/<=>!?:$%_~^";
    let ops = "+-*/|=<>";
    let env = LanguageEnv::new(LanguageDef {
        ident: Identifier {
            start: letter().or(satisfy(|c| alpha_ext.contains(c)))
          , rest: alpha_num().or(satisfy(|c| alpha_ext.contains(c)))
          , reserved: [ "and"               , "begin"
                      , "case"              , "cond"
                      , "data"              , "define"
                      , "defn"              , "delay"
                      , "do"                , "else"
                      , "if"                , "lambda"
                      , "let"               , "let*"
                      , "letrec"            , "or"
                      , "quasiquote"        , "quote"
                      , "set!"              , "unquote"
                      , "unquote-splicing"
                      , "i8"                , "u8"
                      , "i16"               , "u16"
                      , "i32"               , "u32"         , "f32"
                      , "i64"               , "u64"         , "f64"
                      , "int"               , "uint"        , "float"
                      , "bool"                              , "double"
                      ].iter().map(|x| (*x).into()).collect()
        }
      , op: Identifier {
            start: satisfy(|c| ops.contains(c))
          , rest:  satisfy(|c| ops.contains(c))
          , reserved: [ "=>", "->", "\\", "|"].iter().map(|x| (*x).into())
                                                     .collect()
        }
      , comment_line: string(";").map(|_| ())
      , comment_start: string("#|").map(|_| ())
      , comment_end: string("|#").map(|_| ())
    });
    let env = MnEnv { env: env };

    env.white_space()
       .parse(code);

    unimplemented!()
}
<|endoftext|>