<commit_before>// Copyright (c) 2017 Fabian Schuiki

//! This module implements the scoreboard building blocks. Scoreboards are the
//! driving mechanism behind moore. They keep track of the results of each
//! compilation step for every node in the graph. Each node can be accessed in a
//! type safe manner by its ID.

use std;
use std::collections::{BTreeMap, HashMap};
use std::fmt::Debug;
use std::hash::Hash;

use crate::id::NodeId;

/// A context which provides a language-agnostic scoreboard. This is used by
/// the language-specific scoreboards to communicate with the global scoreboard.
pub trait GenericContext {}

/// The `NodeStorage` trait allows for references to nodes to be stored and
/// retrieved via a unique node ID.
///
/// Once a node is created for example in an arena, a reference to it can be
/// stored in a `NodeStorage` to associate it with an ID. If that ID is
/// presented to the `NodeStorage` again, that same reference will be produced.
/// Implementors of this trait are expected to implement it multiple times, once
/// for each different ID/node type pair that they support. This then allows for
/// nodes to be looked up in a type safe manner based on their ID.
///
/// The `NodeStorage` does not assume ownership over the nodes added to it.
/// Therefore all nodes are references of at least the lifetime `'tn`.
///
/// # Example
///
/// ```
/// use moore_common::score::NodeStorage;
/// use std::collections::HashMap;
///
/// #[derive(PartialEq, Eq, Debug)]
/// struct Foo;
/// #[derive(PartialEq, Eq, Debug)]
/// struct Bar;
///
/// #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
/// struct FooId(usize);
/// #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
/// struct BarId(usize);
///
/// struct Table<'tn> {
///     foos: HashMap<FooId, &'tn Foo>,
///     bars: HashMap<BarId, &'tn Bar>,
/// }
///
/// impl<'tn> NodeStorage<FooId> for Table<'tn> {
///     type Node = &'tn Foo;
///     fn get(&self, id: &FooId) -> Option<&&'tn Foo> { self.foos.get(id) }
///     fn set(&mut self, id: FooId, node: &'tn Foo) -> Option<&'tn Foo> { self.foos.insert(id, node) }
/// }
///
/// impl<'tn> NodeStorage<BarId> for Table<'tn> {
///     type Node = &'tn Bar;
///     fn get(&self, id: &BarId) -> Option<&&'tn Bar> { self.bars.get(id) }
///     fn set(&mut self, id: BarId, node: &'tn Bar) -> Option<&'tn Bar> { self.bars.insert(id, node) }
/// }
///
/// // Store node refs in table:
/// let foo = Foo;
/// let bar = Bar;
/// let mut tbl = Table{ foos: HashMap::new(), bars: HashMap::new() };
/// tbl.set(FooId(1), &foo);
/// tbl.set(BarId(2), &bar);
///
/// // Retrieve node refs again:
/// assert_eq!(tbl.get(&FooId(1)), Some(&&foo));
/// assert_eq!(tbl.get(&BarId(2)), Some(&&bar));
/// assert_eq!(tbl.get(&BarId(1)), None);
/// assert_eq!(tbl.get(&FooId(2)), None);
///
/// // The following would produce a compiler error due to type mismatch:
/// // let _: &Foo = *tbl.get(&BarId(1)).unwrap();
/// // let _: &Bar = *tbl.get(&FooId(2)).unwrap();
/// ```
pub trait NodeStorage<I> {
    /// The type of the node that is returned when presented with an ID of type
    /// `I`.
    type Node;

    /// Obtains a reference to the node with the given ID.
    ///
    /// Returns `None` when no node with the given ID exists.
    fn get(&self, id: &I) -> Option<&Self::Node>;

    /// Store a reference to a node under the given ID.
    ///
    /// Later that reference can be retrieved again by presenting the same ID to
    /// the `get` function. Returns the previously stored entry, if any.
    fn set(&mut self, id: I, node: Self::Node) -> Option<Self::Node>;
}

// Implement the NodeStorage trait for HashMaps.
impl<K, V> NodeStorage<K> for HashMap<K, V>
where
    K: Hash + Eq,
{
    type Node = V;

    fn get(&self, id: &K) -> Option<&V> {
        HashMap::get(self, id)
    }

    fn set(&mut self, id: K, node: V) -> Option<V> {
        HashMap::insert(self, id, node)
    }
}

// Implement the NodeStorage trait for BTreeMaps.
impl<K, V> NodeStorage<K> for BTreeMap<K, V>
where
    K: Ord,
{
    type Node = V;

    fn get(&self, id: &K) -> Option<&V> {
        BTreeMap::get(self, id)
    }

    fn set(&mut self, id: K, node: V) -> Option<V> {
        BTreeMap::insert(self, id, node)
    }
}

/// The `NodeMaker` trait allows for nodes to be generated from an ID.
///
/// This is useful in conjunction with the `NodeStorage` and `Scoreboard`
/// traits. If a value is requested that the scoreboard cannot find, this trait
/// allows for the node to be generated. For example, if the AST for a node is
/// requested but does not exist, this trait can be implemented in such a way
/// that said AST is loaded. This allows for complex on-demand loading and
/// compilation to be implemented.
///
/// The nodes are expected to be owned either by the caller or some arena.
/// Therefore only a reference to the created node is returned.
///
/// # Example
///
/// ```
/// use moore_common::score::{self, NodeMaker};
///
/// #[derive(PartialEq, Eq, Debug)]
/// struct Foo;
/// #[derive(PartialEq, Eq, Debug)]
/// struct Bar;
///
/// struct FooId(usize);
/// struct BarId(usize);
///
/// struct Table;
///
/// impl<'tn> NodeMaker<FooId, &'tn Foo> for Table {
///     fn make(&self, id: FooId) -> score::Result<&'tn Foo> {
///         Ok(unsafe { &*(1 as *const Foo) }) // usually you would allocate this in an arena
///     }
/// }
///
/// impl<'tn> NodeMaker<BarId, &'tn Bar> for Table {
///     fn make(&self, id: BarId) -> score::Result<&'tn Bar> {
///         Ok(unsafe { &*(1 as *const Bar) }) // usually you would allocate this in an arena
///     }
/// }
///
/// let tbl = Table;
/// let foo = tbl.make(FooId(1)).unwrap();
/// let bar = tbl.make(BarId(2)).unwrap();
/// assert_eq!(foo, &Foo);
/// assert_eq!(bar, &Bar);
///
/// // The following would produce a compiler error due to type mismatch:
/// // assert_eq!(foo, &Bar);
/// // assert_eq!(bar, &Foo);
/// ```
pub trait NodeMaker<I, N> {
    /// Creates the node with the given ID.
    ///
    /// Returns `Err(())` upon failure. Note that the generated node has
    /// lifetime `'tn` that outlives the `NodeMaker`. This is required to allow
    /// for the `NodeMaker` to generate multiple nodes at the same time. The
    /// generated nodes should be owned by an arena or the owner of the
    /// `NodeMaker` itself.
    fn make(&self, id: I) -> Result<N>;
}

/// The result of making a node. Errors that occur while making a node should be
/// reported via a separate channel, e.g. diagnostics, which provide more
/// information to the user.
pub type Result<T> = std::result::Result<T, ()>;

/// A reference to a node.
///
/// Newtypes around `NodeId` should implement this trait to offer functionality
/// common to all node references.
pub trait NodeRef: Copy + Eq + Ord + Hash + Debug + Into<NodeId> {
    /// Allocate a new reference.
    ///
    /// Creates a new unique reference. Calls `NodeId::alloc()` under the hood.
    fn alloc() -> Self {
        Self::new(NodeId::alloc())
    }

    /// Create a new reference from an existing node ID.
    fn new(id: NodeId) -> Self;
}

/// Create a new node reference.
///
/// This is merely a wrapper around `NodeId` to provide a type safe
/// representation of a node.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate moore_common;
/// # extern crate rustc_serialize;
///
/// # fn main() {
/// node_ref!(FooRef);
/// node_ref!(BarRef);
/// # }
/// ```
///
/// This creates two structs `FooRef` and `BarRef` that both wrap around a
/// `NodeId`.
#[macro_export]
macro_rules! node_ref {
    ($name:ident) => {
        #[derive(
            Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash,
        )]
        pub struct $name($crate::NodeId);

        impl std::fmt::Debug for $name {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{}({:?})", stringify!($name), self.0)
            }
        }

        impl Into<$crate::NodeId> for $name {
            fn into(self) -> $crate::NodeId {
                self.0
            }
        }

        impl $crate::score::NodeRef for $name {
            fn new(id: $crate::NodeId) -> $name {
                $name(id)
            }
        }
    };
}

/// Create a new group of node references.
///
/// This is a simple enum that contains variants for each of the references.
/// Implements `From` for the various references, and `Into<NodeId>`.
#[macro_export]
macro_rules! node_ref_group {
	($name:ident: $($var:ident($ty:ty),)+) => {
		#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
		pub enum $name {
			$($var($ty),)*
		}

		impl std::fmt::Debug for $name {
			fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
				node_ref_group!(MATCHES *self, $($name::$var(id) => write!(f, "{}({:?})", stringify!($var), id)),*)
			}
		}

		impl Into<$crate::NodeId> for $name {
			fn into(self) -> $crate::NodeId {
				node_ref_group!(MATCHES self, $($name::$var(id) => id.into()),*)
			}
		}

		$(
		impl From<$ty> for $name {
			fn from(id: $ty) -> $name {
				$name::$var(id)
			}
		}
		)*
	};

	(MATCHES $value:expr, $($lhs:pat => $rhs:expr),+) => {
		match $value {
			$($lhs => $rhs),+
		}
	};
}

/// Create a new table that implements the `NodeStorage` trait.
///
/// The resulting table can then be used to store nodes in a type safe manner.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate moore_common;
/// use moore_common::score::NodeStorage;
/// # extern crate rustc_serialize;
/// # use std::collections::HashMap;
///
/// #[derive(PartialEq, Eq, Hash, Debug)]
/// struct FooRef(usize);
/// #[derive(PartialEq, Eq, Hash, Debug)]
/// struct BarRef(usize);
///
/// #[derive(PartialEq, Eq, Debug)]
/// struct Foo;
/// #[derive(PartialEq, Eq, Debug)]
/// struct Bar;
///
/// node_storage!(NodeTable<'tn>:
///     foos: FooRef => &'tn Foo,
///     bars: BarRef => &'tn Bar,
/// );
///
/// # fn main() {
/// let foo = &Foo;
/// let bar = &Bar;
///
/// let mut tbl = NodeTable::new();
/// tbl.set(FooRef(0), foo);
/// tbl.set(BarRef(1), bar);
///
/// assert_eq!(tbl.get(&FooRef(0)), Some(&foo));
/// assert_eq!(tbl.get(&BarRef(1)), Some(&bar));
///
/// // The following would produce a compiler error due to the type mismatch:
/// // assert_eq!(tbl.get(&BarRef(0)), Some(&foo));
/// // assert_eq!(tbl.get(&FooRef(1)), Some(&bar));
/// # }
/// ```
#[macro_export]
macro_rules! node_storage {
	($name:ident<$($lt:tt),+>: $($node_name:ident : $node_ref:ty => $node:ty,)+) => {
		pub struct $name<$($lt),*> {
			$($node_name: std::collections::HashMap<$node_ref, $node>,)*
		}

		node_storage!(STRUCT_IMPL $name; $($lt),*; $($node_name, $node_ref, $node;)*);
	};

	($name:ident<$($lt:tt),+> where ($($wh:tt)+): $($node_name:ident : $node_ref:ty => $node:ty,)+) => {
		pub struct $name<$($lt),*> where $($wh)* {
			$($node_name: std::collections::HashMap<$node_ref, $node>,)*
		}

		node_storage!(STRUCT_IMPL $name; $($lt),*; $($node_name, $node_ref, $node;)*);
	};

	(STRUCT_IMPL $name:ident; $($lt:tt),+; $($node_name:ident, $node_ref:ty, $node:ty;)*) => {
		impl<$($lt),*> $name<$($lt),*> {
			/// Create a new empty table.
			pub fn new() -> $name<$($lt),*> {
				$name {
					$($node_name: std::collections::HashMap::new(),)*
				}
			}
		}

		node_storage!(TRAIT_IMPL $name; $($lt),*; $($node_name, $node_ref, $node;)*);
	};

	(TRAIT_IMPL $name:ident; $($lt:tt),+; $node_name:ident, $node_ref:ty, $node:ty; $($tail_name:ident, $tail_ref:ty, $tail:ty;)*) => {
		impl<$($lt),*> $crate::score::NodeStorage<$node_ref> for $name<$($lt),*> {
			type Node = $node;

			fn get(&self, id: &$node_ref) -> Option<&$node> {
				self.$node_name.get(id)
			}

			fn set(&mut self, id: $node_ref, node: $node) -> Option<$node> {
				self.$node_name.insert(id, node)
			}
		}

		node_storage!(TRAIT_IMPL $name; $($lt),*; $($tail_name, $tail_ref, $tail;)*);
	};

	(TRAIT_IMPL $name:ident; $($lt:tt),*;) => {}
}
<commit_msg>rustfmt src/common/score.rs<commit_after>// Copyright (c) 2017 Fabian Schuiki

//! This module implements the scoreboard building blocks. Scoreboards are the
//! driving mechanism behind moore. They keep track of the results of each
//! compilation step for every node in the graph. Each node can be accessed in a
//! type safe manner by its ID.

use std;
use std::collections::{BTreeMap, HashMap};
use std::fmt::Debug;
use std::hash::Hash;

use crate::id::NodeId;

/// A context which provides a language-agnostic scoreboard. This is used by
/// the language-specific scoreboards to communicate with the global scoreboard.
pub trait GenericContext {}

/// The `NodeStorage` trait allows for references to nodes to be stored and
/// retrieved via a unique node ID.
///
/// Once a node is created for example in an arena, a reference to it can be
/// stored in a `NodeStorage` to associate it with an ID. If that ID is
/// presented to the `NodeStorage` again, that same reference will be produced.
/// Implementors of this trait are expected to implement it multiple times, once
/// for each different ID/node type pair that they support. This then allows for
/// nodes to be looked up in a type safe manner based on their ID.
///
/// The `NodeStorage` does not assume ownership over the nodes added to it.
/// Therefore all nodes are references of at least the lifetime `'tn`.
///
/// # Example
///
/// ```
/// use moore_common::score::NodeStorage;
/// use std::collections::HashMap;
///
/// #[derive(PartialEq, Eq, Debug)]
/// struct Foo;
/// #[derive(PartialEq, Eq, Debug)]
/// struct Bar;
///
/// #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
/// struct FooId(usize);
/// #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
/// struct BarId(usize);
///
/// struct Table<'tn> {
///     foos: HashMap<FooId, &'tn Foo>,
///     bars: HashMap<BarId, &'tn Bar>,
/// }
///
/// impl<'tn> NodeStorage<FooId> for Table<'tn> {
///     type Node = &'tn Foo;
///     fn get(&self, id: &FooId) -> Option<&&'tn Foo> { self.foos.get(id) }
///     fn set(&mut self, id: FooId, node: &'tn Foo) -> Option<&'tn Foo> { self.foos.insert(id, node) }
/// }
///
/// impl<'tn> NodeStorage<BarId> for Table<'tn> {
///     type Node = &'tn Bar;
///     fn get(&self, id: &BarId) -> Option<&&'tn Bar> { self.bars.get(id) }
///     fn set(&mut self, id: BarId, node: &'tn Bar) -> Option<&'tn Bar> { self.bars.insert(id, node) }
/// }
///
/// // Store node refs in table:
/// let foo = Foo;
/// let bar = Bar;
/// let mut tbl = Table{ foos: HashMap::new(), bars: HashMap::new() };
/// tbl.set(FooId(1), &foo);
/// tbl.set(BarId(2), &bar);
///
/// // Retrieve node refs again:
/// assert_eq!(tbl.get(&FooId(1)), Some(&&foo));
/// assert_eq!(tbl.get(&BarId(2)), Some(&&bar));
/// assert_eq!(tbl.get(&BarId(1)), None);
/// assert_eq!(tbl.get(&FooId(2)), None);
///
/// // The following would produce a compiler error due to type mismatch:
/// // let _: &Foo = *tbl.get(&BarId(1)).unwrap();
/// // let _: &Bar = *tbl.get(&FooId(2)).unwrap();
/// ```
pub trait NodeStorage<I> {
    /// The type of the node that is returned when presented with an ID of type
    /// `I`.
    type Node;

    /// Obtains a reference to the node with the given ID.
    ///
    /// Returns `None` when no node with the given ID exists.
    fn get(&self, id: &I) -> Option<&Self::Node>;

    /// Store a reference to a node under the given ID.
    ///
    /// Later that reference can be retrieved again by presenting the same ID to
    /// the `get` function. Returns the previously stored entry, if any.
    fn set(&mut self, id: I, node: Self::Node) -> Option<Self::Node>;
}

// Implement the NodeStorage trait for HashMaps.
impl<K, V> NodeStorage<K> for HashMap<K, V>
where
    K: Hash + Eq,
{
    type Node = V;

    fn get(&self, id: &K) -> Option<&V> {
        HashMap::get(self, id)
    }

    fn set(&mut self, id: K, node: V) -> Option<V> {
        HashMap::insert(self, id, node)
    }
}

// Implement the NodeStorage trait for BTreeMaps.
impl<K, V> NodeStorage<K> for BTreeMap<K, V>
where
    K: Ord,
{
    type Node = V;

    fn get(&self, id: &K) -> Option<&V> {
        BTreeMap::get(self, id)
    }

    fn set(&mut self, id: K, node: V) -> Option<V> {
        BTreeMap::insert(self, id, node)
    }
}

/// The `NodeMaker` trait allows for nodes to be generated from an ID.
///
/// This is useful in conjunction with the `NodeStorage` and `Scoreboard`
/// traits. If a value is requested that the scoreboard cannot find, this trait
/// allows for the node to be generated. For example, if the AST for a node is
/// requested but does not exist, this trait can be implemented in such a way
/// that said AST is loaded. This allows for complex on-demand loading and
/// compilation to be implemented.
///
/// The nodes are expected to be owned either by the caller or some arena.
/// Therefore only a reference to the created node is returned.
///
/// # Example
///
/// ```
/// use moore_common::score::{self, NodeMaker};
///
/// #[derive(PartialEq, Eq, Debug)]
/// struct Foo;
/// #[derive(PartialEq, Eq, Debug)]
/// struct Bar;
///
/// struct FooId(usize);
/// struct BarId(usize);
///
/// struct Table;
///
/// impl<'tn> NodeMaker<FooId, &'tn Foo> for Table {
///     fn make(&self, id: FooId) -> score::Result<&'tn Foo> {
///         Ok(unsafe { &*(1 as *const Foo) }) // usually you would allocate this in an arena
///     }
/// }
///
/// impl<'tn> NodeMaker<BarId, &'tn Bar> for Table {
///     fn make(&self, id: BarId) -> score::Result<&'tn Bar> {
///         Ok(unsafe { &*(1 as *const Bar) }) // usually you would allocate this in an arena
///     }
/// }
///
/// let tbl = Table;
/// let foo = tbl.make(FooId(1)).unwrap();
/// let bar = tbl.make(BarId(2)).unwrap();
/// assert_eq!(foo, &Foo);
/// assert_eq!(bar, &Bar);
///
/// // The following would produce a compiler error due to type mismatch:
/// // assert_eq!(foo, &Bar);
/// // assert_eq!(bar, &Foo);
/// ```
pub trait NodeMaker<I, N> {
    /// Creates the node with the given ID.
    ///
    /// Returns `Err(())` upon failure. Note that the generated node has
    /// lifetime `'tn` that outlives the `NodeMaker`. This is required to allow
    /// for the `NodeMaker` to generate multiple nodes at the same time. The
    /// generated nodes should be owned by an arena or the owner of the
    /// `NodeMaker` itself.
    fn make(&self, id: I) -> Result<N>;
}

/// The result of making a node. Errors that occur while making a node should be
/// reported via a separate channel, e.g. diagnostics, which provide more
/// information to the user.
pub type Result<T> = std::result::Result<T, ()>;

/// A reference to a node.
///
/// Newtypes around `NodeId` should implement this trait to offer functionality
/// common to all node references.
pub trait NodeRef: Copy + Eq + Ord + Hash + Debug + Into<NodeId> {
    /// Allocate a new reference.
    ///
    /// Creates a new unique reference. Calls `NodeId::alloc()` under the hood.
    fn alloc() -> Self {
        Self::new(NodeId::alloc())
    }

    /// Create a new reference from an existing node ID.
    fn new(id: NodeId) -> Self;
}

/// Create a new node reference.
///
/// This is merely a wrapper around `NodeId` to provide a type safe
/// representation of a node.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate moore_common;
/// # extern crate rustc_serialize;
///
/// # fn main() {
/// node_ref!(FooRef);
/// node_ref!(BarRef);
/// # }
/// ```
///
/// This creates two structs `FooRef` and `BarRef` that both wrap around a
/// `NodeId`.
#[macro_export]
macro_rules! node_ref {
    ($name:ident) => {
        #[derive(
            Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash,
        )]
        pub struct $name($crate::NodeId);

        impl std::fmt::Debug for $name {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{}({:?})", stringify!($name), self.0)
            }
        }

        impl Into<$crate::NodeId> for $name {
            fn into(self) -> $crate::NodeId {
                self.0
            }
        }

        impl $crate::score::NodeRef for $name {
            fn new(id: $crate::NodeId) -> $name {
                $name(id)
            }
        }
    };
}

/// Create a new group of node references.
///
/// This is a simple enum that contains variants for each of the references.
/// Implements `From` for the various references, and `Into<NodeId>`.
#[macro_export]
macro_rules! node_ref_group {
    ($name:ident: $($var:ident($ty:ty),)+) => {
        #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
        pub enum $name {
            $($var($ty),)*
        }

        impl std::fmt::Debug for $name {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                node_ref_group!(MATCHES *self, $($name::$var(id) => write!(f, "{}({:?})", stringify!($var), id)),*)
            }
        }

        impl Into<$crate::NodeId> for $name {
            fn into(self) -> $crate::NodeId {
                node_ref_group!(MATCHES self, $($name::$var(id) => id.into()),*)
            }
        }

        $(
        impl From<$ty> for $name {
            fn from(id: $ty) -> $name {
                $name::$var(id)
            }
        }
        )*
    };

    (MATCHES $value:expr, $($lhs:pat => $rhs:expr),+) => {
        match $value {
            $($lhs => $rhs),+
        }
    };
}

/// Create a new table that implements the `NodeStorage` trait.
///
/// The resulting table can then be used to store nodes in a type safe manner.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate moore_common;
/// use moore_common::score::NodeStorage;
/// # extern crate rustc_serialize;
/// # use std::collections::HashMap;
///
/// #[derive(PartialEq, Eq, Hash, Debug)]
/// struct FooRef(usize);
/// #[derive(PartialEq, Eq, Hash, Debug)]
/// struct BarRef(usize);
///
/// #[derive(PartialEq, Eq, Debug)]
/// struct Foo;
/// #[derive(PartialEq, Eq, Debug)]
/// struct Bar;
///
/// node_storage!(NodeTable<'tn>:
///     foos: FooRef => &'tn Foo,
///     bars: BarRef => &'tn Bar,
/// );
///
/// # fn main() {
/// let foo = &Foo;
/// let bar = &Bar;
///
/// let mut tbl = NodeTable::new();
/// tbl.set(FooRef(0), foo);
/// tbl.set(BarRef(1), bar);
///
/// assert_eq!(tbl.get(&FooRef(0)), Some(&foo));
/// assert_eq!(tbl.get(&BarRef(1)), Some(&bar));
///
/// // The following would produce a compiler error due to the type mismatch:
/// // assert_eq!(tbl.get(&BarRef(0)), Some(&foo));
/// // assert_eq!(tbl.get(&FooRef(1)), Some(&bar));
/// # }
/// ```
#[macro_export]
macro_rules! node_storage {
    ($name:ident<$($lt:tt),+>: $($node_name:ident : $node_ref:ty => $node:ty,)+) => {
        pub struct $name<$($lt),*> {
            $($node_name: std::collections::HashMap<$node_ref, $node>,)*
        }

        node_storage!(STRUCT_IMPL $name; $($lt),*; $($node_name, $node_ref, $node;)*);
    };

    ($name:ident<$($lt:tt),+> where ($($wh:tt)+): $($node_name:ident : $node_ref:ty => $node:ty,)+) => {
        pub struct $name<$($lt),*> where $($wh)* {
            $($node_name: std::collections::HashMap<$node_ref, $node>,)*
        }

        node_storage!(STRUCT_IMPL $name; $($lt),*; $($node_name, $node_ref, $node;)*);
    };

    (STRUCT_IMPL $name:ident; $($lt:tt),+; $($node_name:ident, $node_ref:ty, $node:ty;)*) => {
        impl<$($lt),*> $name<$($lt),*> {
            /// Create a new empty table.
            pub fn new() -> $name<$($lt),*> {
                $name {
                    $($node_name: std::collections::HashMap::new(),)*
                }
            }
        }

        node_storage!(TRAIT_IMPL $name; $($lt),*; $($node_name, $node_ref, $node;)*);
    };

    (TRAIT_IMPL $name:ident; $($lt:tt),+; $node_name:ident, $node_ref:ty, $node:ty; $($tail_name:ident, $tail_ref:ty, $tail:ty;)*) => {
        impl<$($lt),*> $crate::score::NodeStorage<$node_ref> for $name<$($lt),*> {
            type Node = $node;

            fn get(&self, id: &$node_ref) -> Option<&$node> {
                self.$node_name.get(id)
            }

            fn set(&mut self, id: $node_ref, node: $node) -> Option<$node> {
                self.$node_name.insert(id, node)
            }
        }

        node_storage!(TRAIT_IMPL $name; $($lt),*; $($tail_name, $tail_ref, $tail;)*);
    };

    (TRAIT_IMPL $name:ident; $($lt:tt),*;) => {}
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::convert::From;
use std::iter::repeat;
use std::fs::File;
use std::io;
use std::io::BufRead;
use std::fmt;
use ast::Type;
use span::Span;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ErrorCode
{
    UnexpectedEOF,
    IOError,
    UnexpectedChar,
    UnexpectedToken,
    ExpectedIdentifier,
    ExpectedIntLiteral,
    ExpectedOperator,
    InvalidOperator,
    InvalidUnaryOperator,
    InvalidBinaryOperator,
    InvalidFloatingPoint,
    InvalidInteger,
    TypeError,
    UnknownName,
    MissingType,
    CallingNonCallable,
    CodegenError,
    RedefinitionOfVariable,
    RedefinitionOfFunction,
    RedefinitionOfStruct,
    GenericTypeSubstitutionError,
    ExpressionNotAllowedAtTopLevel,
    LambdaDoesNotMatch,
    WrongArgumentCount,
    UnknownType(String, Type), // Name and expected type
    UnknownStructMember,
    FileNotFound,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CompileError
{
    pub span: Span,
    pub error: ErrorCode,
    pub msg: String,
}

impl CompileError
{
    pub fn new(span: &Span, error: ErrorCode, msg: String) -> CompileError
    {
        CompileError{
            span: span.clone(),
            error: error,
            msg: msg,
        }
    }

    pub fn print(&self)
    {
        let prefix = "> ";
        println!("{}{}: {}", prefix, self.span, self.msg);
        if let Ok(file) = File::open(&self.span.file) {
            let start_line = if self.span.start.line >= 4 {self.span.start.line - 4} else {0};
            let reader = io::BufReader::new(file);

            for (idx, line) in reader.lines().enumerate().skip(start_line)
            {
                let line = line.unwrap();
                let line_idx = idx + 1;
                println!("{:>4}{}{}", line_idx, prefix, line);
                if line_idx == self.span.start.line
                {
                    let end = if line_idx == self.span.end.line {self.span.end.offset} else {line.len()};
                    let carets = repeat_string("^", end - self.span.start.offset + 1);
                    let whitespace = repeat_string(" ", self.span.start.offset - 1);
                    println!("{:>4}{}{}{}", line_idx, prefix, whitespace, carets);
                }
                else if line_idx == self.span.end.line
                {
                    let carets = repeat_string("^", self.span.end.offset);
                    println!("{}{}", prefix, carets);
                }
                else if line_idx > self.span.start.line && line_idx < self.span.end.line
                {
                    let carets = repeat_string("^", line.len());
                    println!("{}{}", prefix, carets);
                }

                if line_idx >= self.span.end.line + 3 {break;}
            }
        }
    }
}

pub type CompileResult<T> = Result<T, CompileError>;

pub fn err<T: Sized>(span: &Span, e: ErrorCode, msg: String) -> CompileResult<T>
{
    Err(CompileError::new(span, e, msg))
}

pub fn unknown_name(span: &Span, name: &str) -> CompileError
{
    CompileError::new(span, ErrorCode::UnknownName, format!("Unable to resolve name {}", name))
}

fn repeat_string(s: &str, count: usize) -> String
{
    repeat(s).take(count).collect()
}

impl fmt::Display for CompileError
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        writeln!(f, "{}: {}", self.span, self.msg)
    }
}

impl Error for CompileError
{
    fn description(&self) -> &str
    {
        "Compile error"
    }
}

impl From<io::Error> for CompileError
{
    fn from(e: io::Error) -> Self
    {
        CompileError{
            span: Span::default(),
            error: ErrorCode::IOError,
            msg: format!("IO Error: {}", e),
        }
    }
}
<commit_msg>Improve error printing<commit_after>use std::error::Error;
use std::convert::From;
use std::iter::repeat;
use std::fs::File;
use std::io;
use std::io::BufRead;
use std::fmt;
use ast::Type;
use span::Span;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ErrorCode
{
    UnexpectedEOF,
    IOError,
    UnexpectedChar,
    UnexpectedToken,
    ExpectedIdentifier,
    ExpectedIntLiteral,
    ExpectedOperator,
    InvalidOperator,
    InvalidUnaryOperator,
    InvalidBinaryOperator,
    InvalidFloatingPoint,
    InvalidInteger,
    TypeError,
    UnknownName,
    MissingType,
    CallingNonCallable,
    CodegenError,
    RedefinitionOfVariable,
    RedefinitionOfFunction,
    RedefinitionOfStruct,
    GenericTypeSubstitutionError,
    ExpressionNotAllowedAtTopLevel,
    LambdaDoesNotMatch,
    WrongArgumentCount,
    UnknownType(String, Type), // Name and expected type
    UnknownStructMember,
    FileNotFound,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CompileError
{
    pub span: Span,
    pub error: ErrorCode,
    pub msg: String,
}

impl CompileError
{
    pub fn new(span: &Span, error: ErrorCode, msg: String) -> CompileError
    {
        CompileError{
            span: span.clone(),
            error: error,
            msg: msg,
        }
    }

    pub fn print(&self)
    {
        let prefix = "| ";
        println!("     {}{}: {}", prefix, self.span, self.msg);
        if let Ok(file) = File::open(&self.span.file) {
            let start_line = if self.span.start.line >= 4 {self.span.start.line - 4} else {0};
            let reader = io::BufReader::new(file);

            for (idx, line) in reader.lines().enumerate().skip(start_line)
            {
                let line = line.unwrap();
                let line_idx = idx + 1;
                println!("{:>4} {}{}", line_idx, prefix, line);
                if line_idx == self.span.start.line
                {
                    let end = if line_idx == self.span.end.line {self.span.end.offset} else {line.len()};
                    let carets = repeat_string("^", end - self.span.start.offset + 1);
                    let whitespace = repeat_string(" ", self.span.start.offset - 1);
                    println!("     {}{}{}", prefix, whitespace, carets);
                }
                else if line_idx == self.span.end.line
                {
                    let carets = repeat_string("^", self.span.end.offset);
                    println!("     {}{}", prefix, carets);
                }
                else if line_idx > self.span.start.line && line_idx < self.span.end.line
                {
                    let carets = repeat_string("^", line.len());
                    println!("    {}{}", prefix, carets);
                }

                if line_idx >= self.span.end.line + 3 {break;}
            }
        }
    }
}

pub type CompileResult<T> = Result<T, CompileError>;

pub fn err<T: Sized>(span: &Span, e: ErrorCode, msg: String) -> CompileResult<T>
{
    Err(CompileError::new(span, e, msg))
}

pub fn unknown_name(span: &Span, name: &str) -> CompileError
{
    CompileError::new(span, ErrorCode::UnknownName, format!("Unable to resolve name {}", name))
}

fn repeat_string(s: &str, count: usize) -> String
{
    repeat(s).take(count).collect()
}

impl fmt::Display for CompileError
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        writeln!(f, "{}: {}", self.span, self.msg)
    }
}

impl Error for CompileError
{
    fn description(&self) -> &str
    {
        "Compile error"
    }
}

impl From<io::Error> for CompileError
{
    fn from(e: io::Error) -> Self
    {
        CompileError{
            span: Span::default(),
            error: ErrorCode::IOError,
            msg: format!("IO Error: {}", e),
        }
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;
use std::env;
use std::fs::create_dir_all;
use ::input::*;
use std::collections::HashSet;
use output::SearchResult;

/// A struct to represent a movie to be attached to actors or directors
#[derive(Debug)]
pub struct Movie {
    pub title: String,
    pub year: String,
}

#[derive(Debug)]
struct Res {
    pub field: i64,
}

#[derive(Debug)]
struct GenreResult {
    pub field: String,
}

/// Checks if a database already exists
pub fn db_exists() -> bool {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");
    path_buf.as_path().exists()
}

/// Returns a connection to existing database
fn get_connection() -> Connection {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");

    let conn = Connection::open(path_buf).unwrap();
    conn
}

/// Creates a database with movies and related information for movie suggestions
/// Movies: movie titles with associated release date and genre
/// Actors: names of all actors
/// Rankings: associates movie ID with IMDb ratings and number of ratings
/// Crew (actors and directors): associates actors/directors with their movies
pub fn create_database() {

    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");

    // creates path if not existing
    create_dir_all(&path_buf);

    path_buf.push("database");
    path_buf.set_extension("db");

    let conn = Connection::open(path_buf).unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS movies (
                  id              INTEGER PRIMARY KEY,
                  title           TEXT NOT NULL,
                  year            TEXT NOT NULL,
                  rating          TEXT NOT NULL,
                  number          TEXT NOT NULL
                  )",
                 &[])
        .unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS genres (
                  movie_id        INTEGER NOT NULL,
                  genre           TEXT NOT NULL
            )",
                 &[])
        .unwrap();
}

/// List of movies with their year of release
pub fn import_movie(title: &str, year: &str, rating: &str, number: &str) {
    let conn = get_connection();

    println!("{}", title.replace("'", "").as_str());
    println!("{:?}", year);
    println!("{:?}", rating);
    println!("{:?}", number);

    conn.execute(&format!("INSERT INTO movies (title, year, rating, number) VALUES ('{}', '{}', \
                           '{}', '{}')",
                          title.replace("'", "''").as_str(),
                          year,
                          rating,
                          number),
                 &[])
        .unwrap();
}

/// Genre information is added to the movie list
pub fn add_genres(title: &str, year: &str, genre: &str) {
    let conn = get_connection();

    let mut stm = conn.prepare(&format!("SELECT id FROM movies WHERE title = '{}' AND year = '{}'",
                          title.replace("'", "''").as_str(),
                          year))
        .unwrap();

    let res = stm.query_map(&[], |x| Res { field: x.get(0) })
        .unwrap();

    let mut existent = false;
    let mut movie_id = 0;

    for tmp in res {
        existent = true;
        movie_id = tmp.unwrap().field;
    }

    if existent {
        conn.execute(&format!("INSERT INTO genres (movie_id, genre) VALUES ('{}', '{}')",
                              movie_id,
                              genre),
                     &[])
            .unwrap();
    }
}

/// List of ratings with information of user ratings
pub fn add_rating(title: &str, year: &str, rank: &str, votes: &str) {
    let conn = get_connection();

    conn.execute(&format!("INSERT INTO rankings (movie_id, score, number) VALUES ((SELECT id \
                           FROM movies WHERE title = '{}' AND year = '{}'), '{}', '{}')",
                          title,
                          year,
                          rank,
                          votes),
                 &[])
        .unwrap();
}

pub fn execute(search_params: SearchParams) -> Vec<SearchResult> {
    // println!("{:?}", search_params);
    let conn = get_connection();
    let mut query = String::new();

    query.push_str("SELECT * FROM movies JOIN (SELECT movie_id FROM genres JOIN (SELECT movie_id \
                    as m_id, COUNT(movie_id) AS ctr FROM (SELECT * FROM genres WHERE ");

    let mut genres_string = String::new();
    let mut genres: HashSet<String> = HashSet::new();

    if !search_params.get_movies().is_empty() {
        let mut movie_query = String::new();
        movie_query.push_str("SELECT genre FROM movies JOIN genres ON id = movie_id WHERE");

        let mut tmp = String::new();

        for movie in search_params.get_movies() {
            if tmp.is_empty() {
                tmp.push_str(format!(" title = '{}'", movie.replace("'", "''")).as_str());
            } else {
                tmp.push_str(format!(" OR title = '{}'", movie.replace("'", "''")).as_str());
            }
        }

        movie_query.push_str(tmp.as_str());

        let mut stm = conn.prepare(movie_query.as_str()).unwrap();

        let res = stm.query_map(&[], |x| GenreResult { field: x.get(0) }).unwrap();

        for genre in res {
            genres.insert(genre.unwrap().field);
        }
    }

    for genre in search_params.get_genres() {
        genres.insert(genre);
    }

    for genre in &genres {
        if genres_string.is_empty() {
            genres_string.push_str(format!("genre = '{}'", genre).as_str());
        } else {
            genres_string.push_str(format!(" OR genre = '{}'", genre).as_str());
        }
    }

    query.push_str(genres_string.as_str());

    query.push_str(format!(") GROUP BY m_id) ON movie_id = m_id WHERE ctr >= {} GROUP BY \
                            movie_id) ON id = movie_id WHERE rating > {} ORDER BY rating DESC",
                           genres.len(),
                           search_params.get_rating())
        .as_str());

    let mut stm = conn.prepare(query.as_str()).unwrap();
    let res = stm.query_map(&[], |x| {
        SearchResult {
            title: x.get(1),
            score: x.get(3),
            number: x.get(4),
            year: x.get(2),
            genres: Vec::new(),
        }
    });

    let mut tmp = Vec::new();
    for movie in res.unwrap() {
        let mut mov = movie.unwrap().clone();

        let mut stm =
            conn.prepare(format!("SELECT genre FROM genres WHERE movie_id = (SELECT id FROM \
                                  movies WHERE title = '{}' AND year = '{}') GROUP BY genre \
                                  ORDER BY genre ASC",
                                 mov.title,
                                 mov.year)
                    .as_str())
                .unwrap();
        let genres = stm.query_map(&[], |x| GenreResult { field: x.get(0) }).unwrap();
        let mut genre = Vec::new();
        for g in genres {
            genre.push(g.unwrap().field);
        }
        mov.genres = genre;
        tmp.push(mov);
    }

    tmp

}
<commit_msg>fixed unused result<commit_after>use rusqlite::Connection;
use std::env;
use std::fs::create_dir_all;
use ::input::*;
use std::collections::HashSet;
use output::SearchResult;
use std::process;

/// A struct to represent a movie to be attached to actors or directors
#[derive(Debug)]
pub struct Movie {
    pub title: String,
    pub year: String,
}

#[derive(Debug)]
struct Res {
    pub field: i64,
}

#[derive(Debug)]
struct GenreResult {
    pub field: String,
}

/// Checks if a database already exists
pub fn db_exists() -> bool {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");
    path_buf.as_path().exists()
}

/// Returns a connection to existing database
fn get_connection() -> Connection {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");

    let conn = Connection::open(path_buf).unwrap();
    conn
}

/// Creates a database with movies and related information for movie suggestions
/// Movies: movie titles with associated release date and genre
/// Actors: names of all actors
/// Rankings: associates movie ID with IMDb ratings and number of ratings
/// Crew (actors and directors): associates actors/directors with their movies
pub fn create_database() {

    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");

    // creates path if not existing
    if create_dir_all(&path_buf).is_err() {
        println!("Error while creating the Database at {:?}", path_buf);
        process::exit(1);
    }

    path_buf.push("database");
    path_buf.set_extension("db");

    let conn = Connection::open(path_buf).unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS movies (
                  id              INTEGER PRIMARY KEY,
                  title           TEXT NOT NULL,
                  year            TEXT NOT NULL,
                  rating          TEXT NOT NULL,
                  number          TEXT NOT NULL
                  )",
                 &[])
        .unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS genres (
                  movie_id        INTEGER NOT NULL,
                  genre           TEXT NOT NULL
            )",
                 &[])
        .unwrap();
}

/// List of movies with their year of release
pub fn import_movie(title: &str, year: &str, rating: &str, number: &str) {
    let conn = get_connection();

    println!("{}", title.replace("'", "").as_str());
    println!("{:?}", year);
    println!("{:?}", rating);
    println!("{:?}", number);

    conn.execute(&format!("INSERT INTO movies (title, year, rating, number) VALUES ('{}', '{}', \
                           '{}', '{}')",
                          title.replace("'", "''").as_str(),
                          year,
                          rating,
                          number),
                 &[])
        .unwrap();
}

/// Genre information is added to the movie list
pub fn add_genres(title: &str, year: &str, genre: &str) {
    let conn = get_connection();

    let mut stm = conn.prepare(&format!("SELECT id FROM movies WHERE title = '{}' AND year = '{}'",
                          title.replace("'", "''").as_str(),
                          year))
        .unwrap();

    let res = stm.query_map(&[], |x| Res { field: x.get(0) })
        .unwrap();

    let mut existent = false;
    let mut movie_id = 0;

    for tmp in res {
        existent = true;
        movie_id = tmp.unwrap().field;
    }

    if existent {
        conn.execute(&format!("INSERT INTO genres (movie_id, genre) VALUES ('{}', '{}')",
                              movie_id,
                              genre),
                     &[])
            .unwrap();
    }
}

/// List of ratings with information of user ratings
pub fn add_rating(title: &str, year: &str, rank: &str, votes: &str) {
    let conn = get_connection();

    conn.execute(&format!("INSERT INTO rankings (movie_id, score, number) VALUES ((SELECT id \
                           FROM movies WHERE title = '{}' AND year = '{}'), '{}', '{}')",
                          title,
                          year,
                          rank,
                          votes),
                 &[])
        .unwrap();
}

pub fn execute(search_params: SearchParams) -> Vec<SearchResult> {
    // println!("{:?}", search_params);
    let conn = get_connection();
    let mut query = String::new();

    query.push_str("SELECT * FROM movies JOIN (SELECT movie_id FROM genres JOIN (SELECT movie_id \
                    as m_id, COUNT(movie_id) AS ctr FROM (SELECT * FROM genres WHERE ");

    let mut genres_string = String::new();
    let mut genres: HashSet<String> = HashSet::new();

    if !search_params.get_movies().is_empty() {
        let mut movie_query = String::new();
        movie_query.push_str("SELECT genre FROM movies JOIN genres ON id = movie_id WHERE");

        let mut tmp = String::new();

        for movie in search_params.get_movies() {
            if tmp.is_empty() {
                tmp.push_str(format!(" title = '{}'", movie.replace("'", "''")).as_str());
            } else {
                tmp.push_str(format!(" OR title = '{}'", movie.replace("'", "''")).as_str());
            }
        }

        movie_query.push_str(tmp.as_str());

        let mut stm = conn.prepare(movie_query.as_str()).unwrap();

        let res = stm.query_map(&[], |x| GenreResult { field: x.get(0) }).unwrap();

        for genre in res {
            genres.insert(genre.unwrap().field);
        }
    }

    for genre in search_params.get_genres() {
        genres.insert(genre);
    }

    for genre in &genres {
        if genres_string.is_empty() {
            genres_string.push_str(format!("genre = '{}'", genre).as_str());
        } else {
            genres_string.push_str(format!(" OR genre = '{}'", genre).as_str());
        }
    }

    query.push_str(genres_string.as_str());

    query.push_str(format!(") GROUP BY m_id) ON movie_id = m_id WHERE ctr >= {} GROUP BY \
                            movie_id) ON id = movie_id WHERE rating > {} ORDER BY rating DESC",
                           genres.len(),
                           search_params.get_rating())
        .as_str());

    let mut stm = conn.prepare(query.as_str()).unwrap();
    let res = stm.query_map(&[], |x| {
        SearchResult {
            title: x.get(1),
            score: x.get(3),
            number: x.get(4),
            year: x.get(2),
            genres: Vec::new(),
        }
    });

    let mut tmp = Vec::new();
    for movie in res.unwrap() {
        let mut mov = movie.unwrap().clone();

        let mut stm =
            conn.prepare(format!("SELECT genre FROM genres WHERE movie_id = (SELECT id FROM \
                                  movies WHERE title = '{}' AND year = '{}') GROUP BY genre \
                                  ORDER BY genre ASC",
                                 mov.title,
                                 mov.year)
                    .as_str())
                .unwrap();
        let genres = stm.query_map(&[], |x| GenreResult { field: x.get(0) }).unwrap();
        let mut genre = Vec::new();
        for g in genres {
            genre.push(g.unwrap().field);
        }
        mov.genres = genre;
        tmp.push(mov);
    }

    tmp

}
<|endoftext|>


<commit_before>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Andrew Hobden (@hoverbear) <andrew@hoverbear.org>
//
// 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.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.
use proc_macro2;
use syn;
use syn::punctuated;
use syn::token;

use derives;
use derives::attrs::{Attrs, Kind, Parser, Ty};
use derives::from_argmatches;
use derives::into_app;

/// Generate a block of code to add arguments/subcommands corresponding to
/// the `fields` to an app.
fn gen_app_augmentation(
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
    app_var: &syn::Ident,
) -> proc_macro2::TokenStream {
    let subcmds: Vec<_> = fields
        .iter()
        .filter_map(|field| {
            let attrs = Attrs::from_field(&field);
            if let Kind::Subcommand(ty) = attrs.kind() {
                let subcmd_type = match (ty, derives::sub_type(&field.ty)) {
                    (Ty::Option, Some(sub_type)) => sub_type,
                    _ => &field.ty,
                };
                let required = if ty == Ty::Option {
                    quote!()
                } else {
                    quote! {
                        let #app_var = #app_var.setting(
                            ::clap::AppSettings::SubcommandRequiredElseHelp
                        );
                    }
                };

                Some(quote!{
                    let #app_var = <#subcmd_type>::augment_app( #app_var );
                    #required
                })
            } else {
                None
            }
        })
        .collect();

    assert!(
        subcmds.len() <= 1,
        "cannot have more than one nested subcommand"
    );

    let args = fields.iter().filter_map(|field| {
        let attrs = Attrs::from_field(field);
        match attrs.kind() {
            Kind::Subcommand(_) => None,
            Kind::FlattenStruct => {
                let ty = &field.ty;
                Some(quote! {
                    let #app_var = <#ty>::augment_app(#app_var);
                    let #app_var = if <#ty>::is_subcommand() {
                        #app_var.setting(::clap::AppSettings::SubcommandRequiredElseHelp)
                    } else {
                        #app_var
                    };
                })
            }
            Kind::Arg(ty) => {
                let convert_type = match ty {
                    Ty::Vec | Ty::Option => derives::sub_type(&field.ty).unwrap_or(&field.ty),
                    _ => &field.ty,
                };

                let occurences = attrs.parser().0 == Parser::FromOccurrences;

                let validator = match *attrs.parser() {
                    (Parser::TryFromStr, ref f) => quote! {
                        .validator(|s| {
                            #f(&s)
                            .map(|_: #convert_type| ())
                            .map_err(|e| e.to_string())
                        })
                    },
                    (Parser::TryFromOsStr, ref f) => quote! {
                        .validator_os(|s| #f(&s).map(|_: #convert_type| ()))
                    },
                    _ => quote!(),
                };

                // @TODO remove unneccessary builders
                let modifier = match ty {
                    Ty::Bool => quote!( .takes_value(false).multiple(false) ),
                    Ty::Option => quote!( .takes_value(true).multiple(false) #validator ),
                    Ty::Vec => quote!( .takes_value(true).multiple(true) #validator ),
                    Ty::Other if occurences => quote!( .takes_value(false).multiple(true) ),
                    Ty::Other => {
                        let required = !attrs.has_method("default_value");
                        quote!( .takes_value(true).multiple(false).required(#required) #validator )
                    }
                };
                let methods = attrs.methods();
                let name = attrs.name();
                Some(quote!{
                    let #app_var = #app_var.arg(
                        ::clap::Arg::with_name(#name)
                            #modifier
                            #methods
                    );
                })
            }
        }
    });

    quote! {{
        #( #args )*
        #( #subcmds )*
        #app_var
    }}
}

fn gen_augment_app_fn(
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
) -> proc_macro2::TokenStream {
    let app_var = syn::Ident::new("app", proc_macro2::Span::call_site());
    let augmentation = gen_app_augmentation(fields, &app_var);
    quote! {
        pub fn augment_app<'a, 'b>(
            #app_var: ::clap::App<'a, 'b>
        ) -> ::clap::App<'a, 'b> {
            #augmentation
        }
    }
}

fn gen_augment_app_for_enum(
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
) -> proc_macro2::TokenStream {
    use syn::Fields::*;

    let subcommands = variants.iter().map(|variant| {
        let name = variant.ident.to_string();
        let attrs = Attrs::from_struct(&variant.attrs, name);
        let app_var = syn::Ident::new("subcommand", proc_macro2::Span::call_site());
        let arg_block = match variant.fields {
            Named(ref fields) => gen_app_augmentation(&fields.named, &app_var),
            Unit => quote!( #app_var ),
            Unnamed(syn::FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
                let ty = &unnamed[0];
                quote! {
                    {
                        let #app_var = <#ty>::augment_app(#app_var);
                        if <#ty>::is_subcommand() {
                            #app_var.setting(
                                ::clap::AppSettings::SubcommandRequiredElseHelp
                            )
                        } else {
                            #app_var
                        }
                    }
                }
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        let name = attrs.name();
        let from_attrs = attrs.methods();
        quote! {
            .subcommand({
                let #app_var = ::clap::SubCommand::with_name(#name);
                let #app_var = #arg_block;
                #app_var#from_attrs
            })
        }
    });

    quote! {
        pub fn augment_app<'a, 'b>(
            app: ::clap::App<'a, 'b>
        ) -> ::clap::App<'a, 'b> {
            app #( #subcommands )*
        }
    }
}

fn gen_from_subcommand(
    name: &syn::Ident,
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
) -> proc_macro2::TokenStream {
    use syn::Fields::*;

    let match_arms = variants.iter().map(|variant| {
        let attrs = Attrs::from_struct(&variant.attrs, variant.ident.to_string());
        let sub_name = attrs.name();
        let variant_name = &variant.ident;
        let constructor_block = match variant.fields {
            Named(ref fields) => from_argmatches::gen_constructor(&fields.named),
            Unit => quote!(),
            Unnamed(ref fields) if fields.unnamed.len() == 1 => {
                let ty = &fields.unnamed[0];
                quote!( ( <#ty as ::clap::FromArgMatches>::from_argmatches(matches) ) )
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        quote! {
            (#sub_name, Some(matches)) =>
                Some(#name :: #variant_name #constructor_block)
        }
    });

    quote! {
        pub fn from_subcommand<'a, 'b>(
            sub: (&'b str, Option<&'b ::clap::ArgMatches<'a>>)
        ) -> Option<Self> {
            match sub {
                #( #match_arms ),*,
                _ => None
            }
        }
    }
}

fn clap_impl_for_struct(
    name: &syn::Ident,
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
    attrs: &[syn::Attribute],
) -> proc_macro2::TokenStream {
    let into_app_impl = into_app::gen_into_app_impl_for_struct(name, attrs);
    let augment_app_fn = gen_augment_app_fn(fields);
    let from_argmatches_impl = from_argmatches::gen_from_argmatches_impl_for_struct(name, fields);
    let parse_fns = gen_parse_fns(name);

    quote! {
        #[allow(unused_variables)]
        impl ::clap::Clap for #name { }

        #into_app_impl

        #from_argmatches_impl

        #[allow(dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_app_fn

            #parse_fns

            pub fn is_subcommand() -> bool { false }
        }
    }
}

fn clap_impl_for_enum(
    name: &syn::Ident,
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
    attrs: &[syn::Attribute],
) -> proc_macro2::TokenStream {
    let into_app_impl = into_app::gen_into_app_impl_for_enum(name, attrs);
    let augment_app_fn = gen_augment_app_for_enum(variants);
    let from_argmatches_impl = from_argmatches::gen_from_argmatches_impl_for_enum(name);
    let from_subcommand = gen_from_subcommand(name, variants);
    let parse_fns = gen_parse_fns(name);

    quote! {
        #[allow(unused_variables)]
        impl ::clap::Clap for #name { }

        #into_app_impl

        #from_argmatches_impl

        #[allow(unused_variables, dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_app_fn

            #from_subcommand

            #parse_fns

            pub fn is_subcommand() -> bool { true }
        }
    }
}

pub fn derive_clap(input: &syn::DeriveInput) -> proc_macro2::TokenStream {
    use syn::Data::*;

    let struct_name = &input.ident;
    let inner_impl = match input.data {
        Struct(syn::DataStruct {
            fields: syn::Fields::Named(ref fields),
            ..
        }) => clap_impl_for_struct(struct_name, &fields.named, &input.attrs),
        Enum(ref e) => clap_impl_for_enum(struct_name, &e.variants, &input.attrs),
        _ => panic!("clap_derive only supports non-tuple structs and enums"),
    };

    quote!(#inner_impl)
}

fn gen_parse_fns(name: &syn::Ident) -> proc_macro2::TokenStream {
    quote! {
        fn parse() -> #name {
            use ::clap::{FromArgMatches, IntoApp};
            #name::from_argmatches(&#name::into_app().get_matches())
        }

        fn try_parse() -> ::std::result::Result<#name, ::clap::Error> {
            use ::clap::{FromArgMatches, IntoApp};
            Ok(#name::from_argmatches(&#name::into_app().get_matches_safe()?))
        }

        fn parse_from<I, T>(itr: I) -> #name
        where
            I: ::std::iter::IntoIterator<Item = T>,
            T: Into<::std::ffi::OsString> + Clone {
            use ::clap::{FromArgMatches, IntoApp};
            #name::from_argmatches(&#name::into_app().get_matches_from(itr))
        }

        fn try_parse_from<I, T>(itr: I) -> ::std::result::Result<#name, ::clap::Error>
        where
            I: ::std::iter::IntoIterator<Item = T>,
            T: Into<::std::ffi::OsString> + Clone {
            use ::clap::{FromArgMatches, IntoApp};
            Ok(#name::from_argmatches(&#name::into_app().get_matches_from_safe(itr)?))
        }
    }
}
<commit_msg>Updates to multiple occurences for v3-clap<commit_after>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Andrew Hobden (@hoverbear) <andrew@hoverbear.org>
//
// 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.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.
use proc_macro2;
use syn;
use syn::punctuated;
use syn::token;

use derives;
use derives::attrs::{Attrs, Kind, Parser, Ty};
use derives::from_argmatches;
use derives::into_app;

/// Generate a block of code to add arguments/subcommands corresponding to
/// the `fields` to an app.
fn gen_app_augmentation(
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
    app_var: &syn::Ident,
) -> proc_macro2::TokenStream {
    let subcmds: Vec<_> = fields
        .iter()
        .filter_map(|field| {
            let attrs = Attrs::from_field(&field);
            if let Kind::Subcommand(ty) = attrs.kind() {
                let subcmd_type = match (ty, derives::sub_type(&field.ty)) {
                    (Ty::Option, Some(sub_type)) => sub_type,
                    _ => &field.ty,
                };
                let required = if ty == Ty::Option {
                    quote!()
                } else {
                    quote! {
                        let #app_var = #app_var.setting(
                            ::clap::AppSettings::SubcommandRequiredElseHelp
                        );
                    }
                };

                Some(quote!{
                    let #app_var = <#subcmd_type>::augment_app( #app_var );
                    #required
                })
            } else {
                None
            }
        })
        .collect();

    assert!(
        subcmds.len() <= 1,
        "cannot have more than one nested subcommand"
    );

    let args = fields.iter().filter_map(|field| {
        let attrs = Attrs::from_field(field);
        match attrs.kind() {
            Kind::Subcommand(_) => None,
            Kind::FlattenStruct => {
                let ty = &field.ty;
                Some(quote! {
                    let #app_var = <#ty>::augment_app(#app_var);
                    let #app_var = if <#ty>::is_subcommand() {
                        #app_var.setting(::clap::AppSettings::SubcommandRequiredElseHelp)
                    } else {
                        #app_var
                    };
                })
            }
            Kind::Arg(ty) => {
                let convert_type = match ty {
                    Ty::Vec | Ty::Option => derives::sub_type(&field.ty).unwrap_or(&field.ty),
                    _ => &field.ty,
                };

                let occurences = attrs.parser().0 == Parser::FromOccurrences;

                let validator = match *attrs.parser() {
                    (Parser::TryFromStr, ref f) => quote! {
                        .validator(|s| {
                            #f(&s)
                            .map(|_: #convert_type| ())
                            .map_err(|e| e.to_string())
                        })
                    },
                    (Parser::TryFromOsStr, ref f) => quote! {
                        .validator_os(|s| #f(&s).map(|_: #convert_type| ()))
                    },
                    _ => quote!(),
                };

                // @TODO remove unneccessary builders
                let modifier = match ty {
                    Ty::Bool => quote!( .takes_value(false).multiple(false) ),
                    Ty::Option => quote!( .takes_value(true).multiple(false) #validator ),
                    Ty::Vec => quote!( .takes_value(true).multiple(true) #validator ),
                    Ty::Other if occurences => {
                        quote!( .takes_value(false).multiple_occurrences(true) )
                    }
                    Ty::Other => {
                        let required = !attrs.has_method("default_value");
                        quote!( .takes_value(true).multiple(false).required(#required) #validator )
                    }
                };
                let methods = attrs.methods();
                let name = attrs.name();
                Some(quote!{
                    let #app_var = #app_var.arg(
                        ::clap::Arg::with_name(#name)
                            #modifier
                            #methods
                    );
                })
            }
        }
    });

    quote! {{
        #( #args )*
        #( #subcmds )*
        #app_var
    }}
}

fn gen_augment_app_fn(
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
) -> proc_macro2::TokenStream {
    let app_var = syn::Ident::new("app", proc_macro2::Span::call_site());
    let augmentation = gen_app_augmentation(fields, &app_var);
    quote! {
        pub fn augment_app<'a, 'b>(
            #app_var: ::clap::App<'a, 'b>
        ) -> ::clap::App<'a, 'b> {
            #augmentation
        }
    }
}

fn gen_augment_app_for_enum(
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
) -> proc_macro2::TokenStream {
    use syn::Fields::*;

    let subcommands = variants.iter().map(|variant| {
        let name = variant.ident.to_string();
        let attrs = Attrs::from_struct(&variant.attrs, name);
        let app_var = syn::Ident::new("subcommand", proc_macro2::Span::call_site());
        let arg_block = match variant.fields {
            Named(ref fields) => gen_app_augmentation(&fields.named, &app_var),
            Unit => quote!( #app_var ),
            Unnamed(syn::FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
                let ty = &unnamed[0];
                quote! {
                    {
                        let #app_var = <#ty>::augment_app(#app_var);
                        if <#ty>::is_subcommand() {
                            #app_var.setting(
                                ::clap::AppSettings::SubcommandRequiredElseHelp
                            )
                        } else {
                            #app_var
                        }
                    }
                }
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        let name = attrs.name();
        let from_attrs = attrs.methods();
        quote! {
            .subcommand({
                let #app_var = ::clap::SubCommand::with_name(#name);
                let #app_var = #arg_block;
                #app_var#from_attrs
            })
        }
    });

    quote! {
        pub fn augment_app<'a, 'b>(
            app: ::clap::App<'a, 'b>
        ) -> ::clap::App<'a, 'b> {
            app #( #subcommands )*
        }
    }
}

fn gen_from_subcommand(
    name: &syn::Ident,
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
) -> proc_macro2::TokenStream {
    use syn::Fields::*;

    let match_arms = variants.iter().map(|variant| {
        let attrs = Attrs::from_struct(&variant.attrs, variant.ident.to_string());
        let sub_name = attrs.name();
        let variant_name = &variant.ident;
        let constructor_block = match variant.fields {
            Named(ref fields) => from_argmatches::gen_constructor(&fields.named),
            Unit => quote!(),
            Unnamed(ref fields) if fields.unnamed.len() == 1 => {
                let ty = &fields.unnamed[0];
                quote!( ( <#ty as ::clap::FromArgMatches>::from_argmatches(matches) ) )
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        quote! {
            (#sub_name, Some(matches)) =>
                Some(#name :: #variant_name #constructor_block)
        }
    });

    quote! {
        pub fn from_subcommand<'a, 'b>(
            sub: (&'b str, Option<&'b ::clap::ArgMatches<'a>>)
        ) -> Option<Self> {
            match sub {
                #( #match_arms ),*,
                _ => None
            }
        }
    }
}

fn clap_impl_for_struct(
    name: &syn::Ident,
    fields: &punctuated::Punctuated<syn::Field, token::Comma>,
    attrs: &[syn::Attribute],
) -> proc_macro2::TokenStream {
    let into_app_impl = into_app::gen_into_app_impl_for_struct(name, attrs);
    let augment_app_fn = gen_augment_app_fn(fields);
    let from_argmatches_impl = from_argmatches::gen_from_argmatches_impl_for_struct(name, fields);
    let parse_fns = gen_parse_fns(name);

    quote! {
        #[allow(unused_variables)]
        impl ::clap::Clap for #name { }

        #into_app_impl

        #from_argmatches_impl

        #[allow(dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_app_fn

            #parse_fns

            pub fn is_subcommand() -> bool { false }
        }
    }
}

fn clap_impl_for_enum(
    name: &syn::Ident,
    variants: &punctuated::Punctuated<syn::Variant, token::Comma>,
    attrs: &[syn::Attribute],
) -> proc_macro2::TokenStream {
    let into_app_impl = into_app::gen_into_app_impl_for_enum(name, attrs);
    let augment_app_fn = gen_augment_app_for_enum(variants);
    let from_argmatches_impl = from_argmatches::gen_from_argmatches_impl_for_enum(name);
    let from_subcommand = gen_from_subcommand(name, variants);
    let parse_fns = gen_parse_fns(name);

    quote! {
        #[allow(unused_variables)]
        impl ::clap::Clap for #name { }

        #into_app_impl

        #from_argmatches_impl

        #[allow(unused_variables, dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_app_fn

            #from_subcommand

            #parse_fns

            pub fn is_subcommand() -> bool { true }
        }
    }
}

pub fn derive_clap(input: &syn::DeriveInput) -> proc_macro2::TokenStream {
    use syn::Data::*;

    let struct_name = &input.ident;
    let inner_impl = match input.data {
        Struct(syn::DataStruct {
            fields: syn::Fields::Named(ref fields),
            ..
        }) => clap_impl_for_struct(struct_name, &fields.named, &input.attrs),
        Enum(ref e) => clap_impl_for_enum(struct_name, &e.variants, &input.attrs),
        _ => panic!("clap_derive only supports non-tuple structs and enums"),
    };

    quote!(#inner_impl)
}

fn gen_parse_fns(name: &syn::Ident) -> proc_macro2::TokenStream {
    quote! {
        fn parse() -> #name {
            use ::clap::{FromArgMatches, IntoApp};
            #name::from_argmatches(&#name::into_app().get_matches())
        }

        fn try_parse() -> ::std::result::Result<#name, ::clap::Error> {
            use ::clap::{FromArgMatches, IntoApp};
            Ok(#name::from_argmatches(&#name::into_app().get_matches_safe()?))
        }

        fn parse_from<I, T>(itr: I) -> #name
        where
            I: ::std::iter::IntoIterator<Item = T>,
            T: Into<::std::ffi::OsString> + Clone {
            use ::clap::{FromArgMatches, IntoApp};
            #name::from_argmatches(&#name::into_app().get_matches_from(itr))
        }

        fn try_parse_from<I, T>(itr: I) -> ::std::result::Result<#name, ::clap::Error>
        where
            I: ::std::iter::IntoIterator<Item = T>,
            T: Into<::std::ffi::OsString> + Clone {
            use ::clap::{FromArgMatches, IntoApp};
            Ok(#name::from_argmatches(&#name::into_app().get_matches_from_safe(itr)?))
        }
    }
}
<|endoftext|>


<commit_before>//! Unimplemented.
<commit_msg>Finish R_ext/BLAS.h as ext/blas.rs<commit_after>// automatically generated by rust-bindgen

pub use super::rs::*;
pub use super::complex::*;

#[link(name = "R")]
extern {
    pub fn dasum_(n: *const ::libc::c_int,
                  dx: *const ::libc::c_double,
                  incx: *const ::libc::c_int)
                  -> ::libc::c_double;
    pub fn daxpy_(n: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  dx: *const ::libc::c_double,
                  incx: *const ::libc::c_int,
                  dy: *mut ::libc::c_double,
                  incy: *const ::libc::c_int)
                  -> ();
    pub fn dcopy_(n: *const ::libc::c_int,
                  dx: *const ::libc::c_double,
                  incx: *const ::libc::c_int,
                  dy: *mut ::libc::c_double,
                  incy: *const ::libc::c_int)
                  -> ();
    pub fn ddot_(n: *const ::libc::c_int,
                 dx: *const ::libc::c_double,
                 incx: *const ::libc::c_int,
                 dy: *const ::libc::c_double,
                 incy: *const ::libc::c_int)
                 -> ::libc::c_double;
    pub fn dnrm2_(n: *const ::libc::c_int,
                  dx: *const ::libc::c_double,
                  incx: *const ::libc::c_int)
                  -> ::libc::c_double;
    pub fn drot_(n: *const ::libc::c_int,
                 dx: *mut ::libc::c_double,
                 incx: *const ::libc::c_int,
                 dy: *mut ::libc::c_double,
                 incy: *const ::libc::c_int,
                 c: *const ::libc::c_double,
                 s: *const ::libc::c_double)
                 -> ();
    pub fn drotg_(a: *const ::libc::c_double,
                  b: *const ::libc::c_double,
                  c: *mut ::libc::c_double,
                  s: *mut ::libc::c_double)
                  -> ();
    pub fn drotm_(n: *const ::libc::c_int,
                  dx: *mut ::libc::c_double,
                  incx: *const ::libc::c_int,
                  dy: *mut ::libc::c_double,
                  incy: *const ::libc::c_int,
                  dparam: *const ::libc::c_double)
                  -> ();
    pub fn drotmg_(dd1: *const ::libc::c_double,
                   dd2: *const ::libc::c_double,
                   dx1: *const ::libc::c_double,
                   dy1: *const ::libc::c_double,
                   param: *mut ::libc::c_double)
                   -> ();
    pub fn dscal_(n: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  dx: *mut ::libc::c_double,
                  incx: *const ::libc::c_int)
                  -> ();
    pub fn dswap_(n: *const ::libc::c_int,
                  dx: *mut ::libc::c_double,
                  incx: *const ::libc::c_int,
                  dy: *mut ::libc::c_double,
                  incy: *const ::libc::c_int)
                  -> ();
    pub fn idamax_(n: *const ::libc::c_int,
                   dx: *const ::libc::c_double,
                   incx: *const ::libc::c_int)
                   -> ::libc::c_int;
    pub fn dgbmv_(trans: *const ::libc::c_char,
                  m: *const ::libc::c_int,
                  n: *const ::libc::c_int,
                  kl: *const ::libc::c_int,
                  ku: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  x: *const ::libc::c_double,
                  incx: *const ::libc::c_int,
                  beta: *const ::libc::c_double,
                  y: *mut ::libc::c_double,
                  incy: *const ::libc::c_int)
                  -> ();
    pub fn dgemv_(trans: *const ::libc::c_char,
                  m: *const ::libc::c_int,
                  n: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  x: *const ::libc::c_double,
                  incx: *const ::libc::c_int,
                  beta: *const ::libc::c_double,
                  y: *mut ::libc::c_double,
                  incy: *const ::libc::c_int)
                  -> ();
    pub fn dsbmv_(uplo: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  k: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  x: *const ::libc::c_double,
                  incx: *const ::libc::c_int,
                  beta: *const ::libc::c_double,
                  y: *mut ::libc::c_double,
                  incy: *const ::libc::c_int)
                  -> ();
    pub fn dspmv_(uplo: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  ap: *const ::libc::c_double,
                  x: *const ::libc::c_double,
                  incx: *const ::libc::c_int,
                  beta: *const ::libc::c_double,
                  y: *mut ::libc::c_double,
                  incy: *const ::libc::c_int)
                  -> ();
    pub fn dsymv_(uplo: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  x: *const ::libc::c_double,
                  incx: *const ::libc::c_int,
                  beta: *const ::libc::c_double,
                  y: *mut ::libc::c_double,
                  incy: *const ::libc::c_int)
                  -> ();
    pub fn dtbmv_(uplo: *const ::libc::c_char,
                  trans: *const ::libc::c_char,
                  diag: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  k: *const ::libc::c_int,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  x: *mut ::libc::c_double,
                  incx: *const ::libc::c_int)
                  -> ();
    pub fn dtpmv_(uplo: *const ::libc::c_char,
                  trans: *const ::libc::c_char,
                  diag: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  ap: *const ::libc::c_double,
                  x: *mut ::libc::c_double,
                  incx: *const ::libc::c_int)
                  -> ();
    pub fn dtrmv_(uplo: *const ::libc::c_char,
                  trans: *const ::libc::c_char,
                  diag: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  x: *mut ::libc::c_double,
                  incx: *const ::libc::c_int)
                  -> ();
    pub fn dtbsv_(uplo: *const ::libc::c_char,
                  trans: *const ::libc::c_char,
                  diag: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  k: *const ::libc::c_int,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  x: *mut ::libc::c_double,
                  incx: *const ::libc::c_int)
                  -> ();
    pub fn dtpsv_(uplo: *const ::libc::c_char,
                  trans: *const ::libc::c_char,
                  diag: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  ap: *const ::libc::c_double,
                  x: *mut ::libc::c_double,
                  incx: *const ::libc::c_int)
                  -> ();
    pub fn dtrsv_(uplo: *const ::libc::c_char,
                  trans: *const ::libc::c_char,
                  diag: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  x: *mut ::libc::c_double,
                  incx: *const ::libc::c_int)
                  -> ();
    pub fn dger_(m: *const ::libc::c_int,
                 n: *const ::libc::c_int,
                 alpha: *const ::libc::c_double,
                 x: *const ::libc::c_double,
                 incx: *const ::libc::c_int,
                 y: *const ::libc::c_double,
                 incy: *const ::libc::c_int,
                 a: *mut ::libc::c_double,
                 lda: *const ::libc::c_int)
                 -> ();
    pub fn dsyr_(uplo: *const ::libc::c_char,
                 n: *const ::libc::c_int,
                 alpha: *const ::libc::c_double,
                 x: *const ::libc::c_double,
                 incx: *const ::libc::c_int,
                 a: *mut ::libc::c_double,
                 lda: *const ::libc::c_int)
                 -> ();
    pub fn dspr_(uplo: *const ::libc::c_char,
                 n: *const ::libc::c_int,
                 alpha: *const ::libc::c_double,
                 x: *const ::libc::c_double,
                 incx: *const ::libc::c_int,
                 ap: *mut ::libc::c_double)
                 -> ();
    pub fn dsyr2_(uplo: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  x: *const ::libc::c_double,
                  incx: *const ::libc::c_int,
                  y: *const ::libc::c_double,
                  incy: *const ::libc::c_int,
                  a: *mut ::libc::c_double,
                  lda: *const ::libc::c_int)
                  -> ();
    pub fn dspr2_(uplo: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  x: *const ::libc::c_double,
                  incx: *const ::libc::c_int,
                  y: *const ::libc::c_double,
                  incy: *const ::libc::c_int,
                  ap: *mut ::libc::c_double)
                  -> ();
    pub fn dgemm_(transa: *const ::libc::c_char,
                  transb: *const ::libc::c_char,
                  m: *const ::libc::c_int,
                  n: *const ::libc::c_int,
                  k: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  b: *const ::libc::c_double,
                  ldb: *const ::libc::c_int,
                  beta: *const ::libc::c_double,
                  c: *mut ::libc::c_double,
                  ldc: *const ::libc::c_int)
                  -> ();
    pub fn dtrsm_(side: *const ::libc::c_char,
                  uplo: *const ::libc::c_char,
                  transa: *const ::libc::c_char,
                  diag: *const ::libc::c_char,
                  m: *const ::libc::c_int,
                  n: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  b: *mut ::libc::c_double,
                  ldb: *const ::libc::c_int)
                  -> ();
    pub fn dtrmm_(side: *const ::libc::c_char,
                  uplo: *const ::libc::c_char,
                  transa: *const ::libc::c_char,
                  diag: *const ::libc::c_char,
                  m: *const ::libc::c_int,
                  n: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  b: *mut ::libc::c_double,
                  ldb: *const ::libc::c_int)
                  -> ();
    pub fn dsymm_(side: *const ::libc::c_char,
                  uplo: *const ::libc::c_char,
                  m: *const ::libc::c_int,
                  n: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  b: *const ::libc::c_double,
                  ldb: *const ::libc::c_int,
                  beta: *const ::libc::c_double,
                  c: *mut ::libc::c_double,
                  ldc: *const ::libc::c_int)
                  -> ();
    pub fn dsyrk_(uplo: *const ::libc::c_char,
                  trans: *const ::libc::c_char,
                  n: *const ::libc::c_int,
                  k: *const ::libc::c_int,
                  alpha: *const ::libc::c_double,
                  a: *const ::libc::c_double,
                  lda: *const ::libc::c_int,
                  beta: *const ::libc::c_double,
                  c: *mut ::libc::c_double,
                  ldc: *const ::libc::c_int)
                  -> ();
    pub fn dsyr2k_(uplo: *const ::libc::c_char,
                   trans: *const ::libc::c_char,
                   n: *const ::libc::c_int,
                   k: *const ::libc::c_int,
                   alpha: *const ::libc::c_double,
                   a: *const ::libc::c_double,
                   lda: *const ::libc::c_int,
                   b: *const ::libc::c_double,
                   ldb: *const ::libc::c_int,
                   beta: *const ::libc::c_double,
                   c: *mut ::libc::c_double,
                   ldc: *const ::libc::c_int)
                   -> ();
    pub fn dcabs1_(z: *mut ::libc::c_double) -> ::libc::c_double;
    pub fn dzasum_(n: *mut ::libc::c_int,
                   zx: *mut Rcomplex,
                   incx: *mut ::libc::c_int)
                   -> ::libc::c_double;
    pub fn dznrm2_(n: *mut ::libc::c_int,
                   x: *mut Rcomplex,
                   incx: *mut ::libc::c_int)
                   -> ::libc::c_double;
    pub fn izamax_(n: *mut ::libc::c_int,
                   zx: *mut Rcomplex,
                   incx: *mut ::libc::c_int)
                   -> ::libc::c_int;
    pub fn zaxpy_(n: *mut ::libc::c_int,
                  za: *mut Rcomplex,
                  zx: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  zy: *mut Rcomplex,
                  incy: *mut ::libc::c_int)
                  -> ();
    pub fn zcopy_(n: *mut ::libc::c_int,
                  zx: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  zy: *mut Rcomplex,
                  incy: *mut ::libc::c_int)
                  -> ();
    pub fn zdotc_(n: *mut ::libc::c_int,
                  zx: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  zy: *mut Rcomplex,
                  incy: *mut ::libc::c_int)
                  -> Rcomplex;
    pub fn zdotu_(n: *mut ::libc::c_int,
                  zx: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  zy: *mut Rcomplex,
                  incy: *mut ::libc::c_int)
                  -> Rcomplex;
    pub fn zdrot_(n: *mut ::libc::c_int,
                  zx: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  zy: *mut Rcomplex,
                  incy: *mut ::libc::c_int,
                  c: *mut ::libc::c_double,
                  s: *mut ::libc::c_double)
                  -> ();
    pub fn zdscal_(n: *mut ::libc::c_int,
                   da: *mut ::libc::c_double,
                   zx: *mut Rcomplex,
                   incx: *mut ::libc::c_int)
                   -> ();
    pub fn zgbmv_(trans: *mut ::libc::c_char,
                  m: *mut ::libc::c_int,
                  n: *mut ::libc::c_int,
                  kl: *mut ::libc::c_int,
                  ku: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  beta: *mut Rcomplex,
                  y: *mut Rcomplex,
                  incy: *mut ::libc::c_int)
                  -> ();
    pub fn zgemm_(transa: *const ::libc::c_char,
                  transb: *const ::libc::c_char,
                  m: *const ::libc::c_int,
                  n: *const ::libc::c_int,
                  k: *const ::libc::c_int,
                  alpha: *const Rcomplex,
                  a: *const Rcomplex,
                  lda: *const ::libc::c_int,
                  b: *const Rcomplex,
                  ldb: *const ::libc::c_int,
                  beta: *const Rcomplex,
                  c: *mut Rcomplex,
                  ldc: *const ::libc::c_int)
                  -> ();
    pub fn zgemv_(trans: *mut ::libc::c_char,
                  m: *mut ::libc::c_int,
                  n: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  beta: *mut Rcomplex,
                  y: *mut Rcomplex,
                  incy: *mut ::libc::c_int)
                  -> ();
    pub fn zgerc_(m: *mut ::libc::c_int,
                  n: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  y: *mut Rcomplex,
                  incy: *mut ::libc::c_int,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int)
                  -> ();
    pub fn zgeru_(m: *mut ::libc::c_int,
                  n: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  y: *mut Rcomplex,
                  incy: *mut ::libc::c_int,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int)
                  -> ();
    pub fn zhbmv_(uplo: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  k: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  beta: *mut Rcomplex,
                  y: *mut Rcomplex,
                  incy: *mut ::libc::c_int)
                  -> ();
    pub fn zhemm_(side: *mut ::libc::c_char,
                  uplo: *mut ::libc::c_char,
                  m: *mut ::libc::c_int,
                  n: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  b: *mut Rcomplex,
                  ldb: *mut ::libc::c_int,
                  beta: *mut Rcomplex,
                  c: *mut Rcomplex,
                  ldc: *mut ::libc::c_int)
                  -> ();
    pub fn zhemv_(uplo: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  beta: *mut Rcomplex,
                  y: *mut Rcomplex,
                  incy: *mut ::libc::c_int)
                  -> ();
    pub fn zher_(uplo: *mut ::libc::c_char,
                 n: *mut ::libc::c_int,
                 alpha: *mut ::libc::c_double,
                 x: *mut Rcomplex,
                 incx: *mut ::libc::c_int,
                 a: *mut Rcomplex,
                 lda: *mut ::libc::c_int)
                 -> ();
    pub fn zher2_(uplo: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  y: *mut Rcomplex,
                  incy: *mut ::libc::c_int,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int)
                  -> ();
    pub fn zher2k_(uplo: *mut ::libc::c_char,
                   trans: *mut ::libc::c_char,
                   n: *mut ::libc::c_int,
                   k: *mut ::libc::c_int,
                   alpha: *mut Rcomplex,
                   a: *mut Rcomplex,
                   lda: *mut ::libc::c_int,
                   b: *mut Rcomplex,
                   ldb: *mut ::libc::c_int,
                   beta: *mut ::libc::c_double,
                   c: *mut Rcomplex,
                   ldc: *mut ::libc::c_int)
                   -> ();
    pub fn zherk_(uplo: *mut ::libc::c_char,
                  trans: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  k: *mut ::libc::c_int,
                  alpha: *mut ::libc::c_double,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  beta: *mut ::libc::c_double,
                  c: *mut Rcomplex,
                  ldc: *mut ::libc::c_int)
                  -> ();
    pub fn zhpmv_(uplo: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  ap: *mut Rcomplex,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  beta: *mut Rcomplex,
                  y: *mut Rcomplex,
                  incy: *mut ::libc::c_int)
                  -> ();
    pub fn zhpr_(uplo: *mut ::libc::c_char,
                 n: *mut ::libc::c_int,
                 alpha: *mut ::libc::c_double,
                 x: *mut Rcomplex,
                 incx: *mut ::libc::c_int,
                 ap: *mut Rcomplex)
                 -> ();
    pub fn zhpr2_(uplo: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  y: *mut Rcomplex,
                  incy: *mut ::libc::c_int,
                  ap: *mut Rcomplex)
                  -> ();
    pub fn zrotg_(ca: *mut Rcomplex,
                  cb: *mut Rcomplex,
                  c: *mut ::libc::c_double,
                  s: *mut Rcomplex)
                  -> ();
    pub fn zscal_(n: *mut ::libc::c_int,
                  za: *mut Rcomplex,
                  zx: *mut Rcomplex,
                  incx: *mut ::libc::c_int)
                  -> ();
    pub fn zswap_(n: *mut ::libc::c_int,
                  zx: *mut Rcomplex,
                  incx: *mut ::libc::c_int,
                  zy: *mut Rcomplex,
                  incy: *mut ::libc::c_int)
                  -> ();
    pub fn zsymm_(side: *mut ::libc::c_char,
                  uplo: *mut ::libc::c_char,
                  m: *mut ::libc::c_int,
                  n: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  b: *mut Rcomplex,
                  ldb: *mut ::libc::c_int,
                  beta: *mut Rcomplex,
                  c: *mut Rcomplex,
                  ldc: *mut ::libc::c_int)
                  -> ();
    pub fn zsyr2k_(uplo: *mut ::libc::c_char,
                   trans: *mut ::libc::c_char,
                   n: *mut ::libc::c_int,
                   k: *mut ::libc::c_int,
                   alpha: *mut Rcomplex,
                   a: *mut Rcomplex,
                   lda: *mut ::libc::c_int,
                   b: *mut Rcomplex,
                   ldb: *mut ::libc::c_int,
                   beta: *mut Rcomplex,
                   c: *mut Rcomplex,
                   ldc: *mut ::libc::c_int)
                   -> ();
    pub fn zsyrk_(uplo: *mut ::libc::c_char,
                  trans: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  k: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  beta: *mut Rcomplex,
                  c: *mut Rcomplex,
                  ldc: *mut ::libc::c_int)
                  -> ();
    pub fn ztbmv_(uplo: *mut ::libc::c_char,
                  trans: *mut ::libc::c_char,
                  diag: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  k: *mut ::libc::c_int,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int)
                  -> ();
    pub fn ztbsv_(uplo: *mut ::libc::c_char,
                  trans: *mut ::libc::c_char,
                  diag: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  k: *mut ::libc::c_int,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int)
                  -> ();
    pub fn ztpmv_(uplo: *mut ::libc::c_char,
                  trans: *mut ::libc::c_char,
                  diag: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  ap: *mut Rcomplex,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int)
                  -> ();
    pub fn ztpsv_(uplo: *mut ::libc::c_char,
                  trans: *mut ::libc::c_char,
                  diag: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  ap: *mut Rcomplex,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int)
                  -> ();
    pub fn ztrmm_(side: *mut ::libc::c_char,
                  uplo: *mut ::libc::c_char,
                  transa: *mut ::libc::c_char,
                  diag: *mut ::libc::c_char,
                  m: *mut ::libc::c_int,
                  n: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  b: *mut Rcomplex,
                  ldb: *mut ::libc::c_int)
                  -> ();
    pub fn ztrmv_(uplo: *mut ::libc::c_char,
                  trans: *mut ::libc::c_char,
                  diag: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int)
                  -> ();
    pub fn ztrsm_(side: *mut ::libc::c_char,
                  uplo: *mut ::libc::c_char,
                  transa: *mut ::libc::c_char,
                  diag: *mut ::libc::c_char,
                  m: *mut ::libc::c_int,
                  n: *mut ::libc::c_int,
                  alpha: *mut Rcomplex,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  b: *mut Rcomplex,
                  ldb: *mut ::libc::c_int)
                  -> ();
    pub fn ztrsv_(uplo: *mut ::libc::c_char,
                  trans: *mut ::libc::c_char,
                  diag: *mut ::libc::c_char,
                  n: *mut ::libc::c_int,
                  a: *mut Rcomplex,
                  lda: *mut ::libc::c_int,
                  x: *mut Rcomplex,
                  incx: *mut ::libc::c_int)
                  -> ();
}
<|endoftext|>