<commit_before>//! API wrappers for common use cases like highlighting strings and
//! files without caring about intermediate semantic representation
//! and caching.

use crate::parsing::{ScopeStack, ParseState, SyntaxReference, SyntaxSet, ScopeStackOp};
use crate::highlighting::{Highlighter, HighlightState, HighlightIterator, Theme, Style};
use std::io::{self, BufReader};
use std::fs::File;
use std::path::Path;
// use util::debug_print_ops;

/// Simple way to go directly from lines of text to colored tokens.
///
/// Depending on how you load the syntaxes (see the [`SyntaxSet`] docs), this can either take
/// strings with trailing `\n`s or without.
///
/// [`SyntaxSet`]: ../parsing/struct.SyntaxSet.html
///
/// # Examples
///
/// Prints colored lines of a string to the terminal
///
/// ```
/// use syntect::easy::HighlightLines;
/// use syntect::parsing::SyntaxSet;
/// use syntect::highlighting::{ThemeSet, Style};
/// use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings};
///
/// // Load these once at the start of your program
/// let ps = SyntaxSet::load_defaults_newlines();
/// let ts = ThemeSet::load_defaults();
///
/// let syntax = ps.find_syntax_by_extension("rs").unwrap();
/// let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
/// let s = "pub struct Wow { hi: u64 }\nfn blah() -> u64 {}";
/// for line in LinesWithEndings::from(s) { // LinesWithEndings enables use of newlines mode
///     let ranges: Vec<(Style, &str)> = h.highlight(line, &ps);
///     let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
///     println!("{}", escaped);
/// }
/// ```
pub struct HighlightLines<'a> {
    highlighter: Highlighter<'a>,
    parse_state: ParseState,
    highlight_state: HighlightState,
}

impl<'a> HighlightLines<'a> {
    pub fn new(syntax: &SyntaxReference, theme: &'a Theme) -> HighlightLines<'a> {
        let highlighter = Highlighter::new(theme);
        let highlight_state = HighlightState::new(&highlighter, ScopeStack::new());
        HighlightLines {
            highlighter,
            parse_state: ParseState::new(syntax),
            highlight_state,
        }
    }

    /// Highlights a line of a file
    pub fn highlight<'b>(&mut self, line: &'b str, syntax_set: &SyntaxSet) -> Vec<(Style, &'b str)> {
        // println!("{}", self.highlight_state.path);
        let ops = self.parse_state.parse_line(line, syntax_set);
        // use util::debug_print_ops;
        // debug_print_ops(line, &ops);
        let iter =
            HighlightIterator::new(&mut self.highlight_state, &ops[..], line, &self.highlighter);
        iter.collect()
    }
}

/// Convenience struct containing everything you need to highlight a file
///
/// Use the `reader` to get the lines of the file and the `highlight_lines` to highlight them. See
/// the [`new`] method docs for more information.
///
/// [`new`]: #method.new
pub struct HighlightFile<'a> {
    pub reader: BufReader<File>,
    pub highlight_lines: HighlightLines<'a>,
}

impl<'a> HighlightFile<'a> {
    /// Constructs a file reader and a line highlighter to get you reading files as fast as possible.
    ///
    /// This auto-detects the syntax from the extension and constructs a [`HighlightLines`] with the
    /// correct syntax and theme.
    ///
    /// [`HighlightLines`]: struct.HighlightLines.html
    ///
    /// # Examples
    ///
    /// Using the `newlines` mode is a bit involved but yields more robust and glitch-free highlighting,
    /// as well as being slightly faster since it can re-use a line buffer.
    ///
    /// ```
    /// use syntect::parsing::SyntaxSet;
    /// use syntect::highlighting::{ThemeSet, Style};
    /// use syntect::util::as_24_bit_terminal_escaped;
    /// use syntect::easy::HighlightFile;
    /// use std::io::BufRead;
    ///
    /// # use std::io;
    /// # fn foo() -> io::Result<()> {
    /// let ss = SyntaxSet::load_defaults_newlines();
    /// let ts = ThemeSet::load_defaults();
    ///
    /// let mut highlighter = HighlightFile::new("testdata/highlight_test.erb", &ss, &ts.themes["base16-ocean.dark"]).unwrap();
    /// let mut line = String::new();
    /// while highlighter.reader.read_line(&mut line)? > 0 {
    ///     {
    ///         let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight(&line, &ss);
    ///         println!("{}", as_24_bit_terminal_escaped(&regions[..], true));
    ///     } // until NLL this scope is needed so we can clear the buffer after
    ///     line.clear(); // read_line appends so we need to clear between lines
    /// }
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// This example uses `reader.lines()` to get lines without a newline character, it's simpler but may break on rare tricky cases.
    ///
    /// ```
    /// use syntect::parsing::SyntaxSet;
    /// use syntect::highlighting::{ThemeSet, Style};
    /// use syntect::util::as_24_bit_terminal_escaped;
    /// use syntect::easy::HighlightFile;
    /// use std::io::BufRead;
    ///
    /// let ss = SyntaxSet::load_defaults_nonewlines();
    /// let ts = ThemeSet::load_defaults();
    ///
    /// let mut highlighter = HighlightFile::new("testdata/highlight_test.erb", &ss, &ts.themes["base16-ocean.dark"]).unwrap();
    /// for maybe_line in highlighter.reader.lines() {
    ///     let line = maybe_line.unwrap();
    ///     let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight(&line, &ss);
    ///     println!("{}", as_24_bit_terminal_escaped(&regions[..], true));
    /// }
    /// ```
    pub fn new<P: AsRef<Path>>(path_obj: P,
                               ss: &SyntaxSet,
                               theme: &'a Theme)
                               -> io::Result<HighlightFile<'a>> {
        let path: &Path = path_obj.as_ref();
        let f = File::open(path)?;
        let syntax = ss.find_syntax_for_file(path)?
            .unwrap_or_else(|| ss.find_syntax_plain_text());

        Ok(HighlightFile {
            reader: BufReader::new(f),
            highlight_lines: HighlightLines::new(syntax, theme),
        })
    }
}

/// Iterator over the regions of a line which a given the operation from the parser applies.
///
/// To use, just keep your own [`ScopeStack`] and then `ScopeStack.apply(op)` the operation that is
/// yielded at the top of your `for` loop over this iterator. Now you have a substring of the line
/// and the scope stack for that token.
///
/// See the `synstats.rs` example for an example of using this iterator.
///
/// **Note:** This will often return empty regions, just `continue` after applying the op if you
/// don't want them.
///
/// [`ScopeStack`]: ../parsing/struct.ScopeStack.html
#[derive(Debug)]
pub struct ScopeRegionIterator<'a> {
    ops: &'a [(usize, ScopeStackOp)],
    line: &'a str,
    index: usize,
    last_str_index: usize,
}

impl<'a> ScopeRegionIterator<'a> {
    pub fn new(ops: &'a [(usize, ScopeStackOp)], line: &'a str) -> ScopeRegionIterator<'a> {
        ScopeRegionIterator {
            ops,
            line,
            index: 0,
            last_str_index: 0,
        }
    }
}

static NOOP_OP: ScopeStackOp = ScopeStackOp::Noop;

impl<'a> Iterator for ScopeRegionIterator<'a> {
    type Item = (&'a str, &'a ScopeStackOp);
    fn next(&mut self) -> Option<Self::Item> {
        if self.index > self.ops.len() {
            return None;
        }

        // region extends up to next operation (ops[index]) or string end if there is none
        // note the next operation may be at, last_str_index, in which case the region is empty
        let next_str_i = if self.index == self.ops.len() {
            self.line.len()
        } else {
            self.ops[self.index].0
        };
        let substr = &self.line[self.last_str_index..next_str_i];
        self.last_str_index = next_str_i;

        // the first region covers everything before the first op, which may be empty
        let op = if self.index == 0 {
            &NOOP_OP
        } else {
            &self.ops[self.index-1].1
        };

        self.index += 1;
        Some((substr, op))
    }
}

#[cfg(all(feature = "assets", any(feature = "dump-load", feature = "dump-load-rs")))]
#[cfg(test)]
mod tests {
    use super::*;
    use crate::parsing::{SyntaxSet, ParseState, ScopeStack};
    use crate::highlighting::ThemeSet;
    use std::str::FromStr;

    #[test]
    fn can_highlight_lines() {
        let ss = SyntaxSet::load_defaults_nonewlines();
        let ts = ThemeSet::load_defaults();
        let syntax = ss.find_syntax_by_extension("rs").unwrap();
        let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
        let ranges = h.highlight("pub struct Wow { hi: u64 }", &ss);
        assert!(ranges.len() > 4);
    }

    #[test]
    fn can_highlight_file() {
        let ss = SyntaxSet::load_defaults_nonewlines();
        let ts = ThemeSet::load_defaults();
        HighlightFile::new("testdata/highlight_test.erb",
                           &ss,
                           &ts.themes["base16-ocean.dark"])
            .unwrap();
    }

    #[test]
    fn can_find_regions() {
        let ss = SyntaxSet::load_defaults_nonewlines();
        let mut state = ParseState::new(ss.find_syntax_by_extension("rb").unwrap());
        let line = "lol =5+2";
        let ops = state.parse_line(line, &ss);

        let mut stack = ScopeStack::new();
        let mut token_count = 0;
        for (s, op) in ScopeRegionIterator::new(&ops, line) {
            stack.apply(op);
            if s.is_empty() { // in this case we don't care about blank tokens
                continue;
            }
            if token_count == 1 {
                assert_eq!(stack, ScopeStack::from_str("source.ruby keyword.operator.assignment.ruby").unwrap());
                assert_eq!(s, "=");
            }
            token_count += 1;
            println!("{:?} {}", s, stack);
        }
        assert_eq!(token_count, 5);
    }

    #[test]
    fn can_find_regions_with_trailing_newline() {
        let ss = SyntaxSet::load_defaults_newlines();
        let mut state = ParseState::new(ss.find_syntax_by_extension("rb").unwrap());
        let lines = ["# hello world\n", "lol=5+2\n"];
        let mut stack = ScopeStack::new();

        for line in lines.iter() {
            let ops = state.parse_line(line, &ss);
            println!("{:?}", ops);

            let mut iterated_ops: Vec<&ScopeStackOp> = Vec::new();
            for (_, op) in ScopeRegionIterator::new(&ops, line) {
                stack.apply(op);
                iterated_ops.push(op);
                println!("{:?}", op);
            }

            let all_ops: Vec<&ScopeStackOp> = ops.iter().map(|t|&t.1).collect();
            assert_eq!(all_ops.len(), iterated_ops.len() - 1); // -1 because we want to ignore the NOOP
        }
    }
}
<commit_msg>easy::tests: Fix clippy::needless-collect warning<commit_after>//! API wrappers for common use cases like highlighting strings and
//! files without caring about intermediate semantic representation
//! and caching.

use crate::parsing::{ScopeStack, ParseState, SyntaxReference, SyntaxSet, ScopeStackOp};
use crate::highlighting::{Highlighter, HighlightState, HighlightIterator, Theme, Style};
use std::io::{self, BufReader};
use std::fs::File;
use std::path::Path;
// use util::debug_print_ops;

/// Simple way to go directly from lines of text to colored tokens.
///
/// Depending on how you load the syntaxes (see the [`SyntaxSet`] docs), this can either take
/// strings with trailing `\n`s or without.
///
/// [`SyntaxSet`]: ../parsing/struct.SyntaxSet.html
///
/// # Examples
///
/// Prints colored lines of a string to the terminal
///
/// ```
/// use syntect::easy::HighlightLines;
/// use syntect::parsing::SyntaxSet;
/// use syntect::highlighting::{ThemeSet, Style};
/// use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings};
///
/// // Load these once at the start of your program
/// let ps = SyntaxSet::load_defaults_newlines();
/// let ts = ThemeSet::load_defaults();
///
/// let syntax = ps.find_syntax_by_extension("rs").unwrap();
/// let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
/// let s = "pub struct Wow { hi: u64 }\nfn blah() -> u64 {}";
/// for line in LinesWithEndings::from(s) { // LinesWithEndings enables use of newlines mode
///     let ranges: Vec<(Style, &str)> = h.highlight(line, &ps);
///     let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
///     println!("{}", escaped);
/// }
/// ```
pub struct HighlightLines<'a> {
    highlighter: Highlighter<'a>,
    parse_state: ParseState,
    highlight_state: HighlightState,
}

impl<'a> HighlightLines<'a> {
    pub fn new(syntax: &SyntaxReference, theme: &'a Theme) -> HighlightLines<'a> {
        let highlighter = Highlighter::new(theme);
        let highlight_state = HighlightState::new(&highlighter, ScopeStack::new());
        HighlightLines {
            highlighter,
            parse_state: ParseState::new(syntax),
            highlight_state,
        }
    }

    /// Highlights a line of a file
    pub fn highlight<'b>(&mut self, line: &'b str, syntax_set: &SyntaxSet) -> Vec<(Style, &'b str)> {
        // println!("{}", self.highlight_state.path);
        let ops = self.parse_state.parse_line(line, syntax_set);
        // use util::debug_print_ops;
        // debug_print_ops(line, &ops);
        let iter =
            HighlightIterator::new(&mut self.highlight_state, &ops[..], line, &self.highlighter);
        iter.collect()
    }
}

/// Convenience struct containing everything you need to highlight a file
///
/// Use the `reader` to get the lines of the file and the `highlight_lines` to highlight them. See
/// the [`new`] method docs for more information.
///
/// [`new`]: #method.new
pub struct HighlightFile<'a> {
    pub reader: BufReader<File>,
    pub highlight_lines: HighlightLines<'a>,
}

impl<'a> HighlightFile<'a> {
    /// Constructs a file reader and a line highlighter to get you reading files as fast as possible.
    ///
    /// This auto-detects the syntax from the extension and constructs a [`HighlightLines`] with the
    /// correct syntax and theme.
    ///
    /// [`HighlightLines`]: struct.HighlightLines.html
    ///
    /// # Examples
    ///
    /// Using the `newlines` mode is a bit involved but yields more robust and glitch-free highlighting,
    /// as well as being slightly faster since it can re-use a line buffer.
    ///
    /// ```
    /// use syntect::parsing::SyntaxSet;
    /// use syntect::highlighting::{ThemeSet, Style};
    /// use syntect::util::as_24_bit_terminal_escaped;
    /// use syntect::easy::HighlightFile;
    /// use std::io::BufRead;
    ///
    /// # use std::io;
    /// # fn foo() -> io::Result<()> {
    /// let ss = SyntaxSet::load_defaults_newlines();
    /// let ts = ThemeSet::load_defaults();
    ///
    /// let mut highlighter = HighlightFile::new("testdata/highlight_test.erb", &ss, &ts.themes["base16-ocean.dark"]).unwrap();
    /// let mut line = String::new();
    /// while highlighter.reader.read_line(&mut line)? > 0 {
    ///     {
    ///         let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight(&line, &ss);
    ///         println!("{}", as_24_bit_terminal_escaped(&regions[..], true));
    ///     } // until NLL this scope is needed so we can clear the buffer after
    ///     line.clear(); // read_line appends so we need to clear between lines
    /// }
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// This example uses `reader.lines()` to get lines without a newline character, it's simpler but may break on rare tricky cases.
    ///
    /// ```
    /// use syntect::parsing::SyntaxSet;
    /// use syntect::highlighting::{ThemeSet, Style};
    /// use syntect::util::as_24_bit_terminal_escaped;
    /// use syntect::easy::HighlightFile;
    /// use std::io::BufRead;
    ///
    /// let ss = SyntaxSet::load_defaults_nonewlines();
    /// let ts = ThemeSet::load_defaults();
    ///
    /// let mut highlighter = HighlightFile::new("testdata/highlight_test.erb", &ss, &ts.themes["base16-ocean.dark"]).unwrap();
    /// for maybe_line in highlighter.reader.lines() {
    ///     let line = maybe_line.unwrap();
    ///     let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight(&line, &ss);
    ///     println!("{}", as_24_bit_terminal_escaped(&regions[..], true));
    /// }
    /// ```
    pub fn new<P: AsRef<Path>>(path_obj: P,
                               ss: &SyntaxSet,
                               theme: &'a Theme)
                               -> io::Result<HighlightFile<'a>> {
        let path: &Path = path_obj.as_ref();
        let f = File::open(path)?;
        let syntax = ss.find_syntax_for_file(path)?
            .unwrap_or_else(|| ss.find_syntax_plain_text());

        Ok(HighlightFile {
            reader: BufReader::new(f),
            highlight_lines: HighlightLines::new(syntax, theme),
        })
    }
}

/// Iterator over the regions of a line which a given the operation from the parser applies.
///
/// To use, just keep your own [`ScopeStack`] and then `ScopeStack.apply(op)` the operation that is
/// yielded at the top of your `for` loop over this iterator. Now you have a substring of the line
/// and the scope stack for that token.
///
/// See the `synstats.rs` example for an example of using this iterator.
///
/// **Note:** This will often return empty regions, just `continue` after applying the op if you
/// don't want them.
///
/// [`ScopeStack`]: ../parsing/struct.ScopeStack.html
#[derive(Debug)]
pub struct ScopeRegionIterator<'a> {
    ops: &'a [(usize, ScopeStackOp)],
    line: &'a str,
    index: usize,
    last_str_index: usize,
}

impl<'a> ScopeRegionIterator<'a> {
    pub fn new(ops: &'a [(usize, ScopeStackOp)], line: &'a str) -> ScopeRegionIterator<'a> {
        ScopeRegionIterator {
            ops,
            line,
            index: 0,
            last_str_index: 0,
        }
    }
}

static NOOP_OP: ScopeStackOp = ScopeStackOp::Noop;

impl<'a> Iterator for ScopeRegionIterator<'a> {
    type Item = (&'a str, &'a ScopeStackOp);
    fn next(&mut self) -> Option<Self::Item> {
        if self.index > self.ops.len() {
            return None;
        }

        // region extends up to next operation (ops[index]) or string end if there is none
        // note the next operation may be at, last_str_index, in which case the region is empty
        let next_str_i = if self.index == self.ops.len() {
            self.line.len()
        } else {
            self.ops[self.index].0
        };
        let substr = &self.line[self.last_str_index..next_str_i];
        self.last_str_index = next_str_i;

        // the first region covers everything before the first op, which may be empty
        let op = if self.index == 0 {
            &NOOP_OP
        } else {
            &self.ops[self.index-1].1
        };

        self.index += 1;
        Some((substr, op))
    }
}

#[cfg(all(feature = "assets", any(feature = "dump-load", feature = "dump-load-rs")))]
#[cfg(test)]
mod tests {
    use super::*;
    use crate::parsing::{SyntaxSet, ParseState, ScopeStack};
    use crate::highlighting::ThemeSet;
    use std::str::FromStr;

    #[test]
    fn can_highlight_lines() {
        let ss = SyntaxSet::load_defaults_nonewlines();
        let ts = ThemeSet::load_defaults();
        let syntax = ss.find_syntax_by_extension("rs").unwrap();
        let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
        let ranges = h.highlight("pub struct Wow { hi: u64 }", &ss);
        assert!(ranges.len() > 4);
    }

    #[test]
    fn can_highlight_file() {
        let ss = SyntaxSet::load_defaults_nonewlines();
        let ts = ThemeSet::load_defaults();
        HighlightFile::new("testdata/highlight_test.erb",
                           &ss,
                           &ts.themes["base16-ocean.dark"])
            .unwrap();
    }

    #[test]
    fn can_find_regions() {
        let ss = SyntaxSet::load_defaults_nonewlines();
        let mut state = ParseState::new(ss.find_syntax_by_extension("rb").unwrap());
        let line = "lol =5+2";
        let ops = state.parse_line(line, &ss);

        let mut stack = ScopeStack::new();
        let mut token_count = 0;
        for (s, op) in ScopeRegionIterator::new(&ops, line) {
            stack.apply(op);
            if s.is_empty() { // in this case we don't care about blank tokens
                continue;
            }
            if token_count == 1 {
                assert_eq!(stack, ScopeStack::from_str("source.ruby keyword.operator.assignment.ruby").unwrap());
                assert_eq!(s, "=");
            }
            token_count += 1;
            println!("{:?} {}", s, stack);
        }
        assert_eq!(token_count, 5);
    }

    #[test]
    fn can_find_regions_with_trailing_newline() {
        let ss = SyntaxSet::load_defaults_newlines();
        let mut state = ParseState::new(ss.find_syntax_by_extension("rb").unwrap());
        let lines = ["# hello world\n", "lol=5+2\n"];
        let mut stack = ScopeStack::new();

        for line in lines.iter() {
            let ops = state.parse_line(line, &ss);
            println!("{:?}", ops);

            let mut iterated_ops: Vec<&ScopeStackOp> = Vec::new();
            for (_, op) in ScopeRegionIterator::new(&ops, line) {
                stack.apply(op);
                iterated_ops.push(op);
                println!("{:?}", op);
            }

            let all_ops = ops.iter().map(|t| &t.1);
            assert_eq!(all_ops.count(), iterated_ops.len() - 1); // -1 because we want to ignore the NOOP
        }
    }
}
<|endoftext|>


<commit_before>
use ndarray::*;

use super::error::*;
use super::layout::*;

use impl2::{LapackScalar, UPLO};

pub trait Eigh<EigVal, EigVec> {
    fn eigh(self, UPLO) -> Result<(EigVal, EigVec)>;
}

impl<A, S, Se> Eigh<ArrayBase<Se, Ix1>, ArrayBase<S, Ix2>> for ArrayBase<S, Ix2>
    where A: LapackScalar,
          S: DataMut<Elem = A>,
          Se: DataOwned<Elem = A::Real>
{
    fn eigh(mut self, uplo: UPLO) -> Result<(ArrayBase<Se, Ix1>, ArrayBase<S, Ix2>)> {
        let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
        Ok((ArrayBase::from_vec(s), self))
    }
}

impl<'a, A, S, Se, So> Eigh<ArrayBase<Se, Ix1>, ArrayBase<So, Ix2>> for &'a ArrayBase<S, Ix2>
    where A: LapackScalar + Copy,
          S: Data<Elem = A>,
          Se: DataOwned<Elem = A::Real>,
          So: DataOwned<Elem = A> + DataMut
{
    fn eigh(self, uplo: UPLO) -> Result<(ArrayBase<Se, Ix1>, ArrayBase<So, Ix2>)> {
        let mut a = replicate(self);
        let s = A::eigh(true, a.square_layout()?, uplo, a.as_allocated_mut()?)?;
        Ok((ArrayBase::from_vec(s), a))
    }
}

impl<'a, A, S, Se> Eigh<ArrayBase<Se, Ix1>, &'a mut ArrayBase<S, Ix2>> for &'a mut ArrayBase<S, Ix2>
    where A: LapackScalar,
          S: DataMut<Elem = A>,
          Se: DataOwned<Elem = A::Real>
{
    fn eigh(mut self, uplo: UPLO) -> Result<(ArrayBase<Se, Ix1>, &'a mut ArrayBase<S, Ix2>)> {
        let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
        Ok((ArrayBase::from_vec(s), self))
    }
}

pub trait EigValsh<EigVal> {
    fn eigvalsh(self, UPLO) -> Result<EigVal>;
}
<commit_msg>impl EigValsh<commit_after>
use ndarray::*;

use super::error::*;
use super::layout::*;

use impl2::{LapackScalar, UPLO};

pub trait Eigh<EigVal, EigVec> {
    fn eigh(self, UPLO) -> Result<(EigVal, EigVec)>;
}

impl<A, S, Se> Eigh<ArrayBase<Se, Ix1>, ArrayBase<S, Ix2>> for ArrayBase<S, Ix2>
    where A: LapackScalar,
          S: DataMut<Elem = A>,
          Se: DataOwned<Elem = A::Real>
{
    fn eigh(mut self, uplo: UPLO) -> Result<(ArrayBase<Se, Ix1>, ArrayBase<S, Ix2>)> {
        let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
        Ok((ArrayBase::from_vec(s), self))
    }
}

impl<'a, A, S, Se, So> Eigh<ArrayBase<Se, Ix1>, ArrayBase<So, Ix2>> for &'a ArrayBase<S, Ix2>
    where A: LapackScalar + Copy,
          S: Data<Elem = A>,
          Se: DataOwned<Elem = A::Real>,
          So: DataOwned<Elem = A> + DataMut
{
    fn eigh(self, uplo: UPLO) -> Result<(ArrayBase<Se, Ix1>, ArrayBase<So, Ix2>)> {
        let mut a = replicate(self);
        let s = A::eigh(true, a.square_layout()?, uplo, a.as_allocated_mut()?)?;
        Ok((ArrayBase::from_vec(s), a))
    }
}

impl<'a, A, S, Se> Eigh<ArrayBase<Se, Ix1>, &'a mut ArrayBase<S, Ix2>> for &'a mut ArrayBase<S, Ix2>
    where A: LapackScalar,
          S: DataMut<Elem = A>,
          Se: DataOwned<Elem = A::Real>
{
    fn eigh(mut self, uplo: UPLO) -> Result<(ArrayBase<Se, Ix1>, &'a mut ArrayBase<S, Ix2>)> {
        let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
        Ok((ArrayBase::from_vec(s), self))
    }
}

pub trait EigValsh<EigVal> {
    fn eigvalsh(self, UPLO) -> Result<EigVal>;
}

impl<A, S, Se> EigValsh<ArrayBase<Se, Ix1>> for ArrayBase<S, Ix2>
    where A: LapackScalar,
          S: DataMut<Elem = A>,
          Se: DataOwned<Elem = A::Real>
{
    fn eigvalsh(mut self, uplo: UPLO) -> Result<ArrayBase<Se, Ix1>> {
        let s = A::eigh(false, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
        Ok(ArrayBase::from_vec(s))
    }
}

impl<'a, A, S, Se> EigValsh<ArrayBase<Se, Ix1>> for &'a ArrayBase<S, Ix2>
    where A: LapackScalar + Copy,
          S: Data<Elem = A>,
          Se: DataOwned<Elem = A::Real>
{
    fn eigvalsh(self, uplo: UPLO) -> Result<ArrayBase<Se, Ix1>> {
        let mut a = self.to_owned();
        let s = A::eigh(false, a.square_layout()?, uplo, a.as_allocated_mut()?)?;
        Ok(ArrayBase::from_vec(s))
    }
}

impl<'a, A, S, Se> EigValsh<ArrayBase<Se, Ix1>> for &'a mut ArrayBase<S, Ix2>
    where A: LapackScalar,
          S: DataMut<Elem = A>,
          Se: DataOwned<Elem = A::Real>
{
    fn eigvalsh(mut self, uplo: UPLO) -> Result<ArrayBase<Se, Ix1>> {
        let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
        Ok(ArrayBase::from_vec(s))
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use anyhow::{bail, Error};

use self::parse::{Parser, RawChunk};
use super::{Graph, Node};

mod parse;

enum Chunk {
    Raw(String),
    Package,
    License,
    Repository,
    Features,
    Name,
}

pub struct Pattern(Vec<Chunk>);

impl Pattern {
    pub fn new(format: &str) -> Result<Pattern, Error> {
        let mut chunks = vec![];

        for raw in Parser::new(format) {
            let chunk = match raw {
                RawChunk::Text(text) => Chunk::Raw(text.to_owned()),
                RawChunk::Argument("p") => Chunk::Package,
                RawChunk::Argument("l") => Chunk::License,
                RawChunk::Argument("r") => Chunk::Repository,
                RawChunk::Argument("f") => Chunk::Features,
                RawChunk::Argument("n") => Chunk::Name,
                RawChunk::Argument(a) => {
                    bail!("unsupported pattern `{}`", a);
                }
                RawChunk::Error(err) => bail!("{}", err),
            };
            chunks.push(chunk);
        }

        Ok(Pattern(chunks))
    }

    pub fn display<'a>(&'a self, graph: &'a Graph<'a>, node_index: usize) -> Display<'a> {
        Display {
            pattern: self,
            graph,
            node_index,
        }
    }
}

pub struct Display<'a> {
    pattern: &'a Pattern,
    graph: &'a Graph<'a>,
    node_index: usize,
}

impl<'a> fmt::Display for Display<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let node = self.graph.node(self.node_index);
        match node {
            Node::Package {
                package_id,
                features,
                ..
            } => {
                let package = self.graph.package_for_id(*package_id);
                for chunk in &self.pattern.0 {
                    match chunk {
                        Chunk::Raw(s) => fmt.write_str(s)?,
                        Chunk::Package => {
                            let proc_macro_suffix = if package.proc_macro() {
                                " (proc-macro)"
                            } else {
                                ""
                            };
                            write!(
                                fmt,
                                "{} v{}{}",
                                package.name(),
                                package.version(),
                                proc_macro_suffix
                            )?;

                            let source_id = package.package_id().source_id();
                            if !source_id.is_default_registry() {
                                write!(fmt, " ({})", source_id)?;
                            }
                        }
                        Chunk::License => {
                            if let Some(license) = &package.manifest().metadata().license {
                                write!(fmt, "{}", license)?;
                            }
                        }
                        Chunk::Repository => {
                            if let Some(repository) = &package.manifest().metadata().repository {
                                write!(fmt, "{}", repository)?;
                            }
                        }
                        Chunk::Features => {
                            write!(fmt, "{}", features.join(","))?;
                        }
                        Chunk::Name => {
                            let pname = package.name().as_str();
                            write!(
                                fmt,
                                "{}",
                                package
                                    .manifest()
                                    .targets()
                                    .iter()
                                    .filter(|t| t.is_dylib() || t.is_lib())
                                    .map(|l| l.name())
                                    .collect::<Vec<_>>()
                                    .get(0)
                                    .unwrap_or(&pname)
                            )?;
                        }
                    }
                }
            }
            Node::Feature { name, node_index } => {
                let for_node = self.graph.node(*node_index);
                match for_node {
                    Node::Package { package_id, .. } => {
                        write!(fmt, "{} feature \"{}\"", package_id.name(), name)?;
                        if self.graph.is_cli_feature(self.node_index) {
                            write!(fmt, " (command-line)")?;
                        }
                    }
                    // The node_index in Node::Feature must point to a package
                    // node, see `add_feature`.
                    _ => panic!("unexpected feature node {:?}", for_node),
                }
            }
        }

        Ok(())
    }
}
<commit_msg>Don't collect into a Vec, just find the target and get its name or default.<commit_after>use std::fmt;

use anyhow::{bail, Error};

use self::parse::{Parser, RawChunk};
use super::{Graph, Node};

mod parse;

enum Chunk {
    Raw(String),
    Package,
    License,
    Repository,
    Features,
    Name,
}

pub struct Pattern(Vec<Chunk>);

impl Pattern {
    pub fn new(format: &str) -> Result<Pattern, Error> {
        let mut chunks = vec![];

        for raw in Parser::new(format) {
            let chunk = match raw {
                RawChunk::Text(text) => Chunk::Raw(text.to_owned()),
                RawChunk::Argument("p") => Chunk::Package,
                RawChunk::Argument("l") => Chunk::License,
                RawChunk::Argument("r") => Chunk::Repository,
                RawChunk::Argument("f") => Chunk::Features,
                RawChunk::Argument("n") => Chunk::Name,
                RawChunk::Argument(a) => {
                    bail!("unsupported pattern `{}`", a);
                }
                RawChunk::Error(err) => bail!("{}", err),
            };
            chunks.push(chunk);
        }

        Ok(Pattern(chunks))
    }

    pub fn display<'a>(&'a self, graph: &'a Graph<'a>, node_index: usize) -> Display<'a> {
        Display {
            pattern: self,
            graph,
            node_index,
        }
    }
}

pub struct Display<'a> {
    pattern: &'a Pattern,
    graph: &'a Graph<'a>,
    node_index: usize,
}

impl<'a> fmt::Display for Display<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let node = self.graph.node(self.node_index);
        match node {
            Node::Package {
                package_id,
                features,
                ..
            } => {
                let package = self.graph.package_for_id(*package_id);
                for chunk in &self.pattern.0 {
                    match chunk {
                        Chunk::Raw(s) => fmt.write_str(s)?,
                        Chunk::Package => {
                            let proc_macro_suffix = if package.proc_macro() {
                                " (proc-macro)"
                            } else {
                                ""
                            };
                            write!(
                                fmt,
                                "{} v{}{}",
                                package.name(),
                                package.version(),
                                proc_macro_suffix
                            )?;

                            let source_id = package.package_id().source_id();
                            if !source_id.is_default_registry() {
                                write!(fmt, " ({})", source_id)?;
                            }
                        }
                        Chunk::License => {
                            if let Some(license) = &package.manifest().metadata().license {
                                write!(fmt, "{}", license)?;
                            }
                        }
                        Chunk::Repository => {
                            if let Some(repository) = &package.manifest().metadata().repository {
                                write!(fmt, "{}", repository)?;
                            }
                        }
                        Chunk::Features => {
                            write!(fmt, "{}", features.join(","))?;
                        }
                        Chunk::Name => {
                            write!(
                                fmt,
                                "{}",
                                package
                                    .manifest()
                                    .targets()
                                    .iter()
                                    .find(|target| target.is_dylib() || target.is_lib())
                                    .map(|lib_target| lib_target.name())
                                    .unwrap_or(&package.name())
                            )?;
                        }
                    }
                }
            }
            Node::Feature { name, node_index } => {
                let for_node = self.graph.node(*node_index);
                match for_node {
                    Node::Package { package_id, .. } => {
                        write!(fmt, "{} feature \"{}\"", package_id.name(), name)?;
                        if self.graph.is_cli_feature(self.node_index) {
                            write!(fmt, " (command-line)")?;
                        }
                    }
                    // The node_index in Node::Feature must point to a package
                    // node, see `add_feature`.
                    _ => panic!("unexpected feature node {:?}", for_node),
                }
            }
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>use expr::*;
use funcs::*;
use env::*;
use parser::*;
use atom::*;
use procedure::*;
use errors::*;
use errors::Error::*;
use std::collections::VecDeque;

fn eval_procedure(p: &Procedure, args: &[Expr], env: &mut Env) ->  ExprResult {
    try!(env.apply(&p.params, args));

    let mut res = Expr::Atom(Atom::Nil);

    for p in p.body.iter() {
        res = try!(eval(&p, env));
    }

    env.pop();

    Ok(res)
}

fn define(args: &[Expr], env: &mut Env) -> ExprResult {
    if args.len() != 2 {
        return Err(Error::InvalidArguments);
    }
    if let Expr::Atom(Atom::Symbol(ref key)) = args[0] {
        env.set(key.clone(), args[1].clone());
        Ok(Expr::Atom(Atom::Nil))
    } else {
        Err(Error::InvalidArguments)
    }
}

fn get(args: &[Expr], env: &Env) -> ExprResult {
    if args.len() != 1 {
        return Err(Error::InvalidArguments)
    }

    if let Expr::Atom(Atom::Symbol(ref s)) = args[0] {
        if let Some(a) = env.get(s) {
            Ok(a.clone())
        } else {
            Ok(Expr::Atom(Atom::Nil))
        }
    } else {
        Err(Error::InvalidArguments)
    }
}

fn eval_args(list: &[SyntaxNode], env: &mut Env) -> Result<Vec<Expr>, Error> {
    list.iter().skip(1).map(|i| eval(i, env)).collect()
}

fn quote(v: &[Node]) -> Result<Expr, Error> {
    Ok(Expr::Node(v[1].clone()))
}

fn reduce_fn_params(l: &[SyntaxNode]) -> Result<Vec<Atom>,Error> {
    let mut v = vec![];

    for node in l {
        match *node {
            SyntaxNode::Node(Node::Atom(ref a)) => v.push(a.clone()),
            _ => {
                return Err(InvalidArguments)
            }
        }
    }
    Ok(v)
}

fn collect_body(l: &[SyntaxNode]) -> Vec<SyntaxNode> {
    l.iter().skip(2).map(|x| x.clone()).collect()
}

fn eval_node(atom: &Atom, list: &[SyntaxNode], env: &mut Env) -> ExprResult {
    match *atom {
        Atom::Symbol(ref s) =>  {
            match s.as_ref() {
                "def" => {
                    let args = try!(eval_args(&list, env));
                    return define(&args, env);
                },
                "fn" => {
                    let params = match list[1] {
                        SyntaxNode::Node(Node::List(ref l)) => try!(reduce_fn_params(l)),
                        _ => {
                            return Err(InvalidArguments)
                        }
                    };

                    let prc = Procedure{ params: params,
                                         body: collect_body(list)
                    };

                    return Ok(Expr::Proc(prc))
                },
                "quote" => {
                    panic!("not done");
                    //return quote(&list);
                },
                "get" => {
                    return get( &try!(eval_args(&list, env)), env);
                },
                "if" => {
                    let predicate = try!(eval(&list[1], env));

                    let truthy = match predicate {
                        Expr::Atom(Atom::Boolean(b)) => b,
                        Expr::Atom(Atom::Nil) => false,
                        _ => true
                    };

                    if truthy {
                        return eval(&list[2], env);
                    } else if list.len() > 2 {
                        return eval(&list[3], env);
                    } else {
                        return Ok(Expr::Atom(Atom::Boolean(false)))
                    }
                },
                _ => ()
            };

            let args = try!(eval_args(&list, env));

            if let Some(r) = try_built_ins(&s, &args, env) {
                return r
            }

            if let Some(&Expr::Proc(ref p)) = env.get(&s) {
                let mut renv = env.clone();
                let r = eval_procedure(p, &args, &mut renv);
                return r
            }

            Ok(Expr::Atom(Atom::Nil))
        },
        _ => {
            Err(Error::NotAFunction)
        }
    }
}

pub fn eval(p: &SyntaxNode, env: &mut Env) -> Result<Expr, Error> {
    match *p {
        SyntaxNode::Node(ref node) => {
            match *node {
                Node::List(ref list) => {
                    if list.is_empty() {
                        return Err(InvalidArguments)
                    }
                    match list[0] {
                        SyntaxNode::Node(Node::Atom(ref atom)) => {
                            return eval_node(atom, list, env)
                        },
                        SyntaxNode::Node(Node::List(_)) => {
                            let r = try!(eval(&list[0], env));

                            match r {
                                Expr::Atom(a) => return eval_node(&a, list, env),
                                Expr::Proc(p) => return eval_procedure(&p, &try!(eval_args(&list, env)), env),
                                _ => {
                                    return Err(InvalidArguments)
                                }
                            }
                        },
                        _ => panic!("not ready")
                    }
                },
                Node::Atom(ref atom) => {
                    match *atom {
                        Atom::Symbol(ref s) => {
                            match env.get(s) {
                                Some(e) => return Ok(e.clone()),
                                _ => return Ok(Expr::Atom(Atom::Nil))
                            }
                        }
                        _ => Ok(Expr::Atom(atom.clone()))
                    }
                }
            }
        },
        SyntaxNode::Quote(ref node) => {
            match *node {
                Node::Atom(ref atom) => {
                    return Ok(Expr::Atom(atom.clone()))
                },
                Node::List(ref list) => {
                    let mut out = VecDeque::with_capacity(list.len());
                    for i in list {
                        let n = try!(eval(i, env));

                        match n {
                            Expr::Atom(ref a) => {
                                out.push_back(a.clone());
                            }
                            _ => {
                                return Err(Error::InvalidArguments)
                            }
                        }
                    }
                    return Ok(Expr::Atom(Atom::List(out)))
                }
            }
            Ok(Expr::Node(node.clone()))
        }
        _ => panic!("argh")
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use parser::*;
    use atom::Atom;
    use env::Env;
    use expr::*;

    #[test]
    fn if_special_form() {
        let x = eval(&tokenize("(if (= 1 1) true false)").unwrap(), &mut Env::new()).unwrap();

        assert_eq!(Expr::Atom(Atom::Boolean(true)), x);
    }

    #[test]
    fn if_special_form_false() {
        let x = eval(&tokenize("(if (= 1 2) true false)").unwrap(), &mut Env::new()).unwrap();

        assert_eq!(Expr::Atom(Atom::Boolean(false)), x);
    }

    #[test]
    fn if_no_else() {
        let x = teval("(if (= 1 1) true)");

        assert_eq!(Expr::Atom(Atom::Boolean(true)), x);
    }

    fn tassert(v: &str) {
        assert_eq!(Expr::Atom(Atom::Boolean(true)), teval(v));
    }

    fn trefute(v: &str) {
        assert_eq!(Expr::Atom(Atom::Boolean(false)), teval(v));
    }

    #[test]
    fn comparisons() {
        tassert("(= 1 1 1 1)");
        trefute("(= 1 0 1 1)");
        tassert("(< 1 5 10)");
        trefute("(< 5 1 20)");
        tassert("(<= 1 1 1 5)");
        trefute("(<= 5 2 1 5)");
        tassert("(> 5 3 2 1)");
        trefute("(> 5 3 2 10)");
        tassert("(>= 5 5 5 3)");
        trefute("(>= 5 5 5 10)");
    }
    use number::Number;

    fn num(i: i64) -> Expr {
        Expr::Atom(Atom::Number(Number::Integer(i)))
    }

    #[test]
    fn adds() {
        assert_eq!(num(5), teval("(+ 2 3)"));
        assert_eq!(num(25), teval("(+ 5 5 5 5 5)"));
    }

    #[test]
    fn subs() {
        assert_eq!(num(0), teval("(- 5 5)"));
        assert_eq!(num(5), teval("(- 20 10 5)"));
    }

    #[test]
    fn muls() {
        assert_eq!(num(0), teval("(* 5 5 5 0)"));
        assert_eq!(num(5), teval("(* 1 5)"));
        assert_eq!(num(-5), teval("(* -1 5)"));
    }

    fn teval(s: &str) -> Expr {
        eval(&tokenize(s).unwrap(), &mut Env::new()).unwrap()
    }

    fn teval_env(s: &str, env: &mut Env) -> ExprResult {
        eval(&tokenize(s).unwrap(), env)
    }

    #[test]
    fn symbol_resolving() {
        let mut env = Env::new();

        teval_env("(def 'foo 5)", &mut env).unwrap();

        assert_eq!(num(0), teval_env("(- foo 5)", &mut env).unwrap());
    }

    #[test]
    fn first_and_rest() {
        assert_eq!(num(0), teval("(first (list 0 1 2))"));
        assert_eq!(teval("(list 1 2)"), teval("(rest (list 0 1 2))"));
    }

    #[test]
    fn simple_func() {
        let mut env = Env::new();
        let _ = eval(&tokenize("(def 'f (fn (r b) (+ r b)))").unwrap(), &mut env).unwrap();
        let res = eval(&tokenize("(f 2 3)").unwrap(), &mut env).unwrap();

        assert_eq!(num(5), res);
    }

    #[test]
    fn quoting() {
        //assert_eq!("(a (+ 1 2) c)", "'(a (+ 1 2) c)");
    }
}
<commit_msg>quote function working correctly<commit_after>use expr::*;
use funcs::*;
use env::*;
use parser::*;
use atom::*;
use procedure::*;
use errors::*;
use errors::Error::*;
use std::collections::VecDeque;

fn eval_procedure(p: &Procedure, args: &[Expr], env: &mut Env) ->  ExprResult {
    try!(env.apply(&p.params, args));

    let mut res = Expr::Atom(Atom::Nil);

    for p in p.body.iter() {
        res = try!(eval(&p, env));
    }

    env.pop();

    Ok(res)
}

fn define(args: &[Expr], env: &mut Env) -> ExprResult {
    if args.len() != 2 {
        return Err(Error::InvalidArguments);
    }
    if let Expr::Atom(Atom::Symbol(ref key)) = args[0] {
        env.set(key.clone(), args[1].clone());
        Ok(Expr::Atom(Atom::Nil))
    } else {
        Err(Error::InvalidArguments)
    }
}

fn get(args: &[Expr], env: &Env) -> ExprResult {
    if args.len() != 1 {
        return Err(Error::InvalidArguments)
    }

    if let Expr::Atom(Atom::Symbol(ref s)) = args[0] {
        if let Some(a) = env.get(s) {
            Ok(a.clone())
        } else {
            Ok(Expr::Atom(Atom::Nil))
        }
    } else {
        Err(Error::InvalidArguments)
    }
}

fn eval_args(list: &[SyntaxNode], env: &mut Env) -> Result<Vec<Expr>, Error> {
    list.iter().skip(1).map(|i| eval(i, env)).collect()
}

fn quote(node: &Node, env: &mut Env) -> Result<Expr, Error> {
    match *node {
        Node::Atom(ref atom) => {
            return Ok(Expr::Atom(atom.clone()))
        },
        Node::List(ref list) => {
            let mut out = VecDeque::with_capacity(list.len());
            for i in list {
                let n = try!(eval(i, env));

                match n {
                    Expr::Atom(ref a) => {
                        out.push_back(a.clone());
                    }
                    _ => {
                        return Err(Error::InvalidArguments)
                    }
                }
            }
            return Ok(Expr::Atom(Atom::List(out)))
        }
    }
    Ok(Expr::Node(node.clone()))
}

fn reduce_fn_params(l: &[SyntaxNode]) -> Result<Vec<Atom>,Error> {
    l.iter().map(|node|
                 match *node {
                     SyntaxNode::Node(Node::Atom(ref a)) => Ok(a.clone()),
                     _ => Err(InvalidArguments)
                 }).collect()
}

fn collect_body(l: &[SyntaxNode]) -> Vec<SyntaxNode> {
    l.iter().skip(2).map(|x| x.clone()).collect()
}

fn eval_node(atom: &Atom, list: &[SyntaxNode], env: &mut Env) -> ExprResult {
    match *atom {
        Atom::Symbol(ref s) =>  {
            match s.as_ref() {
                "def" => {
                    let args = try!(eval_args(&list, env));
                    return define(&args, env);
                },
                "fn" => {
                    let params = match list[1] {
                        SyntaxNode::Node(Node::List(ref l)) => try!(reduce_fn_params(l)),
                        _ => {
                            return Err(InvalidArguments)
                        }
                    };

                    let prc = Procedure{ params: params,
                                         body: collect_body(list)
                    };

                    return Ok(Expr::Proc(prc))
                },
                "quote" => {
                    if list.len() > 2 {
                        return Err(InvalidArguments)
                    }
                    match list[1] {
                        SyntaxNode::Node(ref node) => {
                            return quote(node, env)
                        }
                        _ => {
                            return Err(InvalidArguments)
                        }
                    }
                    return Err(NotImplemented)
                    //return quote(&list)
                },
                "get" => {
                    return get( &try!(eval_args(&list, env)), env);
                },
                "if" => {
                    let predicate = try!(eval(&list[1], env));

                    let truthy = match predicate {
                        Expr::Atom(Atom::Boolean(b)) => b,
                        Expr::Atom(Atom::Nil) => false,
                        _ => true
                    };

                    if truthy {
                        return eval(&list[2], env);
                    } else if list.len() > 2 {
                        return eval(&list[3], env);
                    } else {
                        return Ok(Expr::Atom(Atom::Boolean(false)))
                    }
                },
                _ => ()
            };

            let args = try!(eval_args(&list, env));

            if let Some(r) = try_built_ins(&s, &args, env) {
                return r
            }

            if let Some(&Expr::Proc(ref p)) = env.get(&s) {
                let mut renv = env.clone();
                let r = eval_procedure(p, &args, &mut renv);
                return r
            }

            Ok(Expr::Atom(Atom::Nil))
        },
        _ => {
            Err(Error::NotAFunction)
        }
    }
}

pub fn eval(p: &SyntaxNode, env: &mut Env) -> Result<Expr, Error> {
    match *p {
        SyntaxNode::Node(ref node) => {
            match *node {
                Node::List(ref list) => {
                    if list.is_empty() {
                        return Err(InvalidArguments)
                    }
                    match list[0] {
                        SyntaxNode::Node(Node::Atom(ref atom)) => {
                            return eval_node(atom, list, env)
                        },
                        SyntaxNode::Node(Node::List(_)) => {
                            let r = try!(eval(&list[0], env));

                            match r {
                                Expr::Atom(a) => return eval_node(&a, list, env),
                                Expr::Proc(p) => return eval_procedure(&p, &try!(eval_args(&list, env)), env),
                                _ => {
                                    return Err(InvalidArguments)
                                }
                            }
                        },
                        _ => panic!("not ready")
                    }
                },
                Node::Atom(ref atom) => {
                    match *atom {
                        Atom::Symbol(ref s) => {
                            match env.get(s) {
                                Some(e) => return Ok(e.clone()),
                                _ => return Ok(Expr::Atom(Atom::Nil))
                            }
                        }
                        _ => Ok(Expr::Atom(atom.clone()))
                    }
                }
            }
        },
        SyntaxNode::Quote(ref node) => {
            quote(node, env)
       }
        _ => panic!("argh")
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use parser::*;
    use atom::Atom;
    use env::Env;
    use expr::*;

    #[test]
    fn if_special_form() {
        let x = eval(&tokenize("(if (= 1 1) true false)").unwrap(), &mut Env::new()).unwrap();

        assert_eq!(Expr::Atom(Atom::Boolean(true)), x);
    }

    #[test]
    fn if_special_form_false() {
        let x = eval(&tokenize("(if (= 1 2) true false)").unwrap(), &mut Env::new()).unwrap();

        assert_eq!(Expr::Atom(Atom::Boolean(false)), x);
    }

    #[test]
    fn if_no_else() {
        let x = teval("(if (= 1 1) true)");

        assert_eq!(Expr::Atom(Atom::Boolean(true)), x);
    }

    fn tassert(v: &str) {
        assert_eq!(Expr::Atom(Atom::Boolean(true)), teval(v));
    }

    fn trefute(v: &str) {
        assert_eq!(Expr::Atom(Atom::Boolean(false)), teval(v));
    }

    #[test]
    fn comparisons() {
        tassert("(= 1 1 1 1)");
        trefute("(= 1 0 1 1)");
        tassert("(< 1 5 10)");
        trefute("(< 5 1 20)");
        tassert("(<= 1 1 1 5)");
        trefute("(<= 5 2 1 5)");
        tassert("(> 5 3 2 1)");
        trefute("(> 5 3 2 10)");
        tassert("(>= 5 5 5 3)");
        trefute("(>= 5 5 5 10)");
    }
    use number::Number;

    fn num(i: i64) -> Expr {
        Expr::Atom(Atom::Number(Number::Integer(i)))
    }

    #[test]
    fn adds() {
        assert_eq!(num(5), teval("(+ 2 3)"));
        assert_eq!(num(25), teval("(+ 5 5 5 5 5)"));
    }

    #[test]
    fn subs() {
        assert_eq!(num(0), teval("(- 5 5)"));
        assert_eq!(num(5), teval("(- 20 10 5)"));
    }

    #[test]
    fn muls() {
        assert_eq!(num(0), teval("(* 5 5 5 0)"));
        assert_eq!(num(5), teval("(* 1 5)"));
        assert_eq!(num(-5), teval("(* -1 5)"));
    }

    fn teval(s: &str) -> Expr {
        eval(&tokenize(s).unwrap(), &mut Env::new()).unwrap()
    }

    fn teval_env(s: &str, env: &mut Env) -> ExprResult {
        eval(&tokenize(s).unwrap(), env)
    }

    #[test]
    fn symbol_resolving() {
        let mut env = Env::new();

        teval_env("(def 'foo 5)", &mut env).unwrap();

        assert_eq!(num(0), teval_env("(- foo 5)", &mut env).unwrap());
    }

    #[test]
    fn first_and_rest() {
        assert_eq!(num(0), teval("(first (list 0 1 2))"));
        assert_eq!(teval("(list 1 2)"), teval("(rest (list 0 1 2))"));
    }

    #[test]
    fn simple_func() {
        let mut env = Env::new();
        let _ = eval(&tokenize("(def 'f (fn (r b) (+ r b)))").unwrap(), &mut env).unwrap();
        let res = eval(&tokenize("(f 2 3)").unwrap(), &mut env).unwrap();

        assert_eq!(num(5), res);
    }

    #[test]
    fn quote_func() {
       assert_eq!(teval("'(1 2)"), teval("(quote (1 2))"));
        //assert_eq!(Ok(Expr::Atom(Atom::Symbol("a".to_string()))), teval("'a"));
        //assert_eq!("(a (+ 1 2) c)", "'(a (+ 1 2) c)");
    }
}
<|endoftext|>


<commit_before>#[cfg(test)]
mod wasi_sdk_tests {
    use lucet_validate::{self, ModuleType};
    use std::path::PathBuf;
    use witx;

    fn wasi_sdk_test_source_file(name: &str) -> PathBuf {
        let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        p.push("..");
        p.push("lucet-wasi-sdk");
        p.push("tests");
        p.push(name);
        assert!(p.exists(), "test file does not exist");
        p
    }

    fn compile_to_wasm(filename: &str) -> Vec<u8> {
        use lucet_wasi_sdk::Link;
        use std::fs::File;
        use std::io::Read;
        use tempfile::TempDir;

        let tmp = TempDir::new().expect("create temporary directory");

        let wasmfile = tmp.path().join("out.wasm");
        let linker = Link::new(&[wasi_sdk_test_source_file(filename)]);
        linker.link(wasmfile.clone()).expect("link out.wasm");

        let mut module_contents = Vec::new();
        let mut file = File::open(wasmfile).expect("open out.wasm");
        file.read_to_end(&mut module_contents)
            .expect("read out.wasm");

        module_contents
    }

    #[test]
    fn moduletype_of_compiled() {
        let main_wasm = compile_to_wasm("main_returns.c");
        let _moduletype = ModuleType::parse_wasm(&main_wasm).expect("main_returns has module type");
    }

    #[test]
    fn validate_compiled() {
        let main_wasm = compile_to_wasm("main_returns.c");
        let wasi_spec = witx::load("../wasi/phases/unstable/witx/wasi_unstable_preview0.witx")
            .expect("load wasi_unstable_preview0");
        lucet_validate::validate(&wasi_spec, &main_wasm, true).expect("validation");
    }
}
<commit_msg>delete lucet-validate's wasi-sdk test: that testis now inside lucet-wasi-sdk<commit_after><|endoftext|>


<commit_before>use field::{Field, Content};
use piston_window::*;

pub struct Game {
    field: Field,
    glyphs: Glyphs,
    mouse_x: f64,
    mouse_y: f64
}

impl Game {
    pub fn new(glyphs: Glyphs) -> Game {
        Game {
            field: Field::new(20, 15, 50),
            glyphs: glyphs,
            mouse_x: 0.0,
            mouse_y: 0.0
        }
    }

    pub fn render(&mut self, window: &PistonWindow) {
        self.draw_field(window);
    }

    fn get_max_field_size(&self, window: &PistonWindow) -> [u32; 2] {
        [2*window.size().width/3, window.size().height]
    }

    fn draw_field(&mut self, window: &PistonWindow) {
        let max_field_size = self.get_max_field_size(window);
        let cell_w = (max_field_size[0] / self.field.get_width()) as f64;
        let cell_h = (max_field_size[1] / self.field.get_height()) as f64;
        window.draw_2d(|c, g| {
            clear([0.0, 0.0, 0.0, 1.0], g);
            for i in 0..self.field.get_width() {
                for j in 0..self.field.get_height() {
                    if !self.field.revealed(i + j*self.field.get_width()) {
                        continue;
                    }
                    match *self.field.get_content(i + j*self.field.get_width()) {
                        Content::Bomb => {
                            rectangle([1.0, 0.0, 0.0, 1.0],
                                      [(i as f64)*cell_w, (j as f64)*cell_h, cell_w, cell_h],
                                      c.transform, g);

                        },
                        Content::Number(n) => {
                            let transform = c.transform.trans((i as f64)*cell_w + 10.0, (j as f64)*cell_h + cell_h - 5.0);
                            text::Text::colored([1.0, 1.0, 1.0, 1.0], 32).draw(
                                &*n.to_string(),
                                &mut self.glyphs,
                                &c.draw_state,
                                transform, g
                            );
                        },
                        Content::None => {
                            rectangle([1.0, 1.0, 1.0, 1.0],
                                      [(i as f64)*cell_w, (j as f64)*cell_h, cell_w, cell_h],
                                      c.transform, g);
                        }
                    }
                }
            }
            let field_size = [cell_w*(self.field.get_width() as f64), cell_h*(self.field.get_height() as f64)];
            for i in 0..self.field.get_width()+1 {
                line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                    .draw([(i as f64)*cell_w, 0.0, (i as f64)*cell_w, field_size[1]],
                          &c.draw_state,
                          c.transform, g);
                line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                    .draw([0.0, (i as f64)*cell_h, field_size[0], (i as f64)*cell_h],
                          &c.draw_state,
                          c.transform, g);
            }
        });
    }

    pub fn proc_key(&mut self, button: Button, window: &PistonWindow) {
        match button {
            Button::Keyboard(key) => {
                match key {
                    Key::R => self.field.restart(),
                    _ => println!("{:?}", key)
                }
            },
            Button::Mouse(btn) => {
                match btn {
                    MouseButton::Left => {
                        let max_field_size = self.get_max_field_size(window);
                        let cell_w = max_field_size[0] / self.field.get_width();
                        let cell_h = max_field_size[1] / self.field.get_height();
                        if (self.mouse_x > (cell_w*self.field.get_width()) as f64) ||
                            (self.mouse_y > (cell_h*self.field.get_height())  as f64) {
                                return;
                            }
                        let x = (self.mouse_x.floor() as u32)/cell_w;
                        let y = (self.mouse_y.floor() as u32)/cell_h;
                        let w = self.field.get_width();
                        self.open_cell(x + y*w);
                    },
                    _ => println!("{:?}", btn)
                }
            }
        }
    }

    fn open_cell(&mut self, i: u32) {
        match *self.field.reveal(i) {
            Content::Bomb => {
                self.field.reveal_all();
                println!("Game over =(, {}", i);
            },
            Content::None => {
               self.field.chain_reveal(i);
            }
            _ => println!("ok {}", i)
        }
    }

    pub fn mouse_move(&mut self, mouse_rel: [f64; 2]) {
        self.mouse_x = mouse_rel[0];
        self.mouse_y = mouse_rel[1];
    }
}<commit_msg>style: changed code somehow<commit_after>use field::{Field, Content};
use piston_window::*;

pub struct Game {
    field: Field,
    glyphs: Glyphs,
    mouse_x: f64,
    mouse_y: f64
}

impl Game {
    pub fn new(glyphs: Glyphs) -> Game {
        Game {
            field: Field::new(20, 15, 50),
            glyphs: glyphs,
            mouse_x: 0.0,
            mouse_y: 0.0
        }
    }

    pub fn render(&mut self, window: &PistonWindow) {
        window.draw_2d(|c, g| {
            let max_field_size = self.get_max_field_size(window);
            self.draw_field(c, g, max_field_size);
        });
    }

    fn get_max_field_size(&self, window: &PistonWindow) -> [u32; 2] {
        [2*window.size().width/3, window.size().height]
    }

    fn draw_field(&mut self, context: Context, graphics: &mut G2d, max_field_size: [u32; 2]) {
        let cell_w = (max_field_size[0] / self.field.get_width()) as f64;
        let cell_h = (max_field_size[1] / self.field.get_height()) as f64;
        clear([0.0, 0.0, 0.0, 1.0], graphics);
        for i in 0..self.field.get_width() {
            for j in 0..self.field.get_height() {
                if !self.field.revealed(i + j*self.field.get_width()) {
                    continue;
                }
                match *self.field.get_content(i + j*self.field.get_width()) {
                    Content::Bomb => {
                        rectangle([1.0, 0.0, 0.0, 1.0],
                                  [(i as f64)*cell_w, (j as f64)*cell_h, cell_w, cell_h],
                                  context.transform,
                                  graphics);

                    },
                    Content::Number(n) => {
                        let transform = context.transform.trans((i as f64)*cell_w + 10.0, (j as f64)*cell_h + cell_h - 5.0);
                        text::Text::colored([1.0, 1.0, 1.0, 1.0], 32).draw(
                            &*n.to_string(),
                            &mut self.glyphs,
                            &context.draw_state,
                            transform,
                            graphics
                        );
                    },
                    Content::None => {
                        rectangle([1.0, 1.0, 1.0, 1.0],
                                  [(i as f64)*cell_w, (j as f64)*cell_h, cell_w, cell_h],
                                  context.transform,
                                  graphics);
                    }
                }
            }
        }
        let field_size = [cell_w*(self.field.get_width() as f64), cell_h*(self.field.get_height() as f64)];
        for i in 0..self.field.get_width()+1 {
            line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                .draw([(i as f64)*cell_w, 0.0, (i as f64)*cell_w, field_size[1]],
                      &context.draw_state,
                      context.transform,
                      graphics);
            line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                .draw([0.0, (i as f64)*cell_h, field_size[0], (i as f64)*cell_h],
                      &context.draw_state,
                      context.transform,
                      graphics);
        }
    }

    pub fn proc_key(&mut self, button: Button, window: &PistonWindow) {
        match button {
            Button::Keyboard(key) => {
                match key {
                    Key::R => self.field.restart(),
                    _ => println!("{:?}", key)
                }
            },
            Button::Mouse(btn) => {
                match btn {
                    MouseButton::Left => {
                        let max_field_size = self.get_max_field_size(window);
                        let cell_w = max_field_size[0] / self.field.get_width();
                        let cell_h = max_field_size[1] / self.field.get_height();
                        if (self.mouse_x > (cell_w*self.field.get_width()) as f64) ||
                            (self.mouse_y > (cell_h*self.field.get_height())  as f64) {
                                return;
                            }
                        let x = (self.mouse_x.floor() as u32)/cell_w;
                        let y = (self.mouse_y.floor() as u32)/cell_h;
                        let w = self.field.get_width();
                        self.open_cell(x + y*w);
                    },
                    _ => println!("{:?}", btn)
                }
            }
        }
    }

    fn open_cell(&mut self, i: u32) {
        match *self.field.reveal(i) {
            Content::Bomb => {
                self.field.reveal_all();
                println!("Game over =(, {}", i);
            },
            Content::None => {
               self.field.chain_reveal(i);
            }
            _ => println!("ok {}", i)
        }
    }

    pub fn mouse_move(&mut self, mouse_rel: [f64; 2]) {
        self.mouse_x = mouse_rel[0];
        self.mouse_y = mouse_rel[1];
    }
}<|endoftext|>


<commit_before>// Module for SoundHandler

use effect::EffectOption;
use io::sprite::Sprite;
use coord::Coordinate;
use renderable::Renderable;
use io::all_sprites::SpriteMap;
use player::Player;
use actor::Actor;

use gfx_device_gl::Resources;
use gfx_device_gl::CommandBuffer;
use gfx_graphics::GfxGraphics;
use piston_window::*;

/// Represents An Item
/// sprite: The Sprite of the Item
/// heal: > 0 if Item heals player
/// coord: Coordinate of ItemType
/// item_type: The Type of the ItemType
/// gone: If item is collected, it is gone and will be wasted
pub struct Item<'a> {
    pub sprite: Option<&'a Sprite>,
    pub heal: u32,
    pub coord: Coordinate,
    pub item_type: Option<ItemType>,
    pub gone: bool,
}

impl<'a> Item<'a> {
    /// Constructor
    pub fn new(x: u64, y: u64) -> Self {
        Item {
            sprite: None,
            heal: 0,
            coord: Coordinate::new(x, y),
            item_type: None,
            gone: false,
        }
    }

    /// Loads the sprite by given string from SpriteMap
    pub fn load_sprite(&mut self, map: &'a SpriteMap, sprite_str: String) {
        self.sprite = map.map.get(sprite_str.as_str());
        println!("{}", sprite_str);
        self.item_type = match sprite_str.as_str() {
            //If Weapon
            "weapon_dagger.png" => Some(ItemType::Weapon(EffectOption::Dagger)),
            "weapon_broadsword.png" => Some(ItemType::Weapon(EffectOption::Sword)),
            "weapon_spear.png" => Some(ItemType::Weapon(EffectOption::Spear)),
            // If Heal Item
            "Heart_10.png" => Some(ItemType::Heal(10)),
            "Heart_20.png" => Some(ItemType::Heal(20)),
            _ => None,
        }
    }

    /// collects an Item if Player is on same field.
    pub fn collect(&mut self, player: &mut Player<'a>) {
        if player.coord.get_x() == self.coord.get_x() &&
           player.coord.get_y() == self.coord.get_y() && !self.get_gone() {
            if let Some(ref item) = self.item_type {
                match *item {
                    // Cahnge Weapon
                    ItemType::Weapon(weapon) => player.weapon = weapon,
                    // Heal
                    ItemType::Heal(heal) => player.damage_taken(heal as i32 * -1),
                }
            }
            self.gone();
        }
    }

    /// getter for gone
    pub fn get_gone(&self) -> bool {
        self.gone
    }

    /// Item will be gone
    pub fn gone(&mut self) {
        self.gone = true;
    }
}

/// Types of Items
pub enum ItemType {
    Weapon(EffectOption),
    Heal(u8),
}

impl<'a> Renderable for Item<'a> {
    /// Renders the Item
    fn render(&self, g: &mut GfxGraphics<Resources, CommandBuffer>, view: math::Matrix2d) {
        if let Some(ref x) = self.sprite {
            x.render(g, view, 0, false, 0);

        } else {
            //println!("None");
        }

    }
}
<commit_msg> animated items are allowed<commit_after>// Module for SoundHandler

use effect::EffectOption;
use io::sprite::Sprite;
use coord::Coordinate;
use renderable::Renderable;
use io::all_sprites::SpriteMap;
use player::Player;
use actor::Actor;

use gfx_device_gl::Resources;
use gfx_device_gl::CommandBuffer;
use gfx_graphics::GfxGraphics;
use piston_window::*;
use time::PreciseTime;

/// Represents An Item
/// sprite: The Sprite of the Item
/// heal: > 0 if Item heals player
/// coord: Coordinate of ItemType
/// item_type: The Type of the ItemType
/// gone: If item is collected, it is gone and will be wasted
pub struct Item<'a> {
    pub sprite: Option<&'a Sprite>,
    pub heal: u32,
    pub coord: Coordinate,
    pub item_type: Option<ItemType>,
    pub gone: bool,
    pub dt: PreciseTime,
}

impl<'a> Item<'a> {
    /// Constructor
    pub fn new(x: u64, y: u64) -> Self {
        Item {
            sprite: None,
            heal: 0,
            coord: Coordinate::new(x, y),
            item_type: None,
            gone: false,
            dt: PreciseTime::now(),
        }
    }

    /// Loads the sprite by given string from SpriteMap
    pub fn load_sprite(&mut self, map: &'a SpriteMap, sprite_str: String) {
        self.sprite = map.map.get(sprite_str.as_str());
        println!("{}", sprite_str);
        self.item_type = match sprite_str.as_str() {
            //If Weapon
            "weapon_dagger.png" => Some(ItemType::Weapon(EffectOption::Dagger)),
            "weapon_broadsword.png" => Some(ItemType::Weapon(EffectOption::Sword)),
            "weapon_spear.png" => Some(ItemType::Weapon(EffectOption::Spear)),
            // If Heal Item
            "Heart_10.png" => Some(ItemType::Heal(10)),
            "Heart_20.png" => Some(ItemType::Heal(20)),
            _ => None,
        }
    }

    /// collects an Item if Player is on same field.
    pub fn collect(&mut self, player: &mut Player<'a>) {
        if self.dt.to(PreciseTime::now()).num_milliseconds() > 1000 {
                self.dt = PreciseTime::now();
            }
        if player.coord.get_x() == self.coord.get_x() &&
           player.coord.get_y() == self.coord.get_y() && !self.get_gone() {
            if let Some(ref item) = self.item_type {
                match *item {
                    // Cahnge Weapon
                    ItemType::Weapon(weapon) => player.weapon = weapon,
                    // Heal
                    ItemType::Heal(heal) => player.damage_taken(heal as i32 * -1),
                }
            }
            self.gone();
        }
    }

    /// getter for gone
    pub fn get_gone(&self) -> bool {
        self.gone
    }

    /// Item will be gone
    pub fn gone(&mut self) {
        self.gone = true;
    }
}

/// Types of Items
pub enum ItemType {
    Weapon(EffectOption),
    Heal(u8),
}

impl<'a> Renderable for Item<'a> {
    /// Renders the Item
    fn render(&self, g: &mut GfxGraphics<Resources, CommandBuffer>, view: math::Matrix2d) {
        if let Some(ref x) = self.sprite {
            x.render(g, view, self.dt.to(PreciseTime::now()).num_milliseconds() as u64, false, 0);
        } else {
            //println!("None");
        }

    }
}
<|endoftext|>


<commit_before>use rlua::{self, Lua};
use wlroots::{key_events::KeyEvent, xkbcommon::xkb::{KEY_Escape, KEY_Super_L, KEY_Super_R},
              Capability, CompositorHandle, KeyboardHandle, KeyboardHandler, KeyboardModifier,
              WLR_KEY_PRESSED};

use awesome::{self, emit_object_signal, Objectable, LUA, ROOT_KEYS_HANDLE};
use compositor::Server;

pub struct Keyboard;

fn key_is_meta(key: u32) -> bool {
    // TODO configure meta key
    key == KEY_Super_L || key == KEY_Super_R
}

impl KeyboardHandler for Keyboard {
    fn on_key(&mut self, compositor: CompositorHandle, keyboard: KeyboardHandle, event: &KeyEvent) {
        let modifiers = dehandle!(
            @compositor = {compositor};
            if event.key_state() == WLR_KEY_PRESSED {
                for key in event.pressed_keys() {
                    if key == KEY_Escape {
                        // NOTE No need to call awesome::lua::terminate.
                        // that will be handled by wlroots.
                        ::wlroots::terminate();
                    }
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = true;
                    }
                }
            } else {
                for key in event.pressed_keys() {
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = false;
                    }
                }
            };
            let server: &mut Server = compositor.into();
            @seat = {&server.seat.seat};
            @keyboard = {keyboard};
            seat.set_keyboard(keyboard.input_device());
            seat.keyboard_notify_key(event.time_msec(),
                                        event.keycode(),
                                        event.key_state() as u32);
            seat.keyboard_send_modifiers(&mut keyboard.get_modifier_masks());
            keyboard.get_modifiers()
        );
        LUA.with(|lua| {
                     let lua = lua.borrow();
                     if let Err(err) = emit_awesome_keybindings(&*lua, event, modifiers) {
                         warn!("Could not emit binding for {}: {:?}", event.keycode(), err);
                     }
                 });
    }

    fn modifiers(&mut self, compositor: CompositorHandle, keyboard: KeyboardHandle) {
        dehandle!(
            @compositor = {compositor};
            let server: &mut Server = compositor.into();
            @seat = {&server.seat.seat};
            @keyboard = {keyboard};
            seat.keyboard_notify_modifiers(&mut keyboard.get_modifier_masks())
        );
    }

    fn destroyed(&mut self, compositor: CompositorHandle, keyboard: KeyboardHandle) {
        with_handles!([(compositor: {compositor}), (keyboard: {keyboard})] => {
            let server: &mut Server = compositor.into();
            let weak_reference = keyboard.weak_reference();
            if let Some(index) = server.keyboards.iter().position(|k| *k == weak_reference) {
                server.keyboards.remove(index);
                if server.keyboards.len() == 0 {
                    with_handles!([(seat: {&mut server.seat.seat})] => {
                        let mut capabilities = seat.capabilities();
                        capabilities.remove(Capability::Keyboard);
                        seat.set_capabilities(capabilities);
                    }).expect("Seat was destroyed")
                }
            }
        }).unwrap();
    }
}

/// Emits the Awesome keybindinsg.
fn emit_awesome_keybindings(lua: &Lua,
                            event: &KeyEvent,
                            event_modifiers: KeyboardModifier)
                            -> rlua::Result<()> {
    let state_string = if event.key_state() == WLR_KEY_PRESSED {
        "press"
    } else {
        "release"
    };
    // TODO Should also emit by current focused client so we can
    // do client based rules.
    let keybindings = lua.named_registry_value::<Vec<rlua::AnyUserData>>(ROOT_KEYS_HANDLE)?;
    for event_keysym in event.pressed_keys() {
        for binding in &keybindings {
            let obj: awesome::Object = binding.clone().into();
            let key = awesome::Key::cast(obj.clone()).unwrap();
            let keycode = key.keycode()?;
            let keysym = key.keysym()?;
            let modifiers = key.modifiers()?;
            let binding_match = (keysym != 0 && keysym == event_keysym
                                 || keycode != 0 && keycode == event.keycode())
                                && modifiers == 0
                                || modifiers == event_modifiers.bits();
            if binding_match {
                emit_object_signal(&*lua, obj, state_string.into(), event_keysym)?;
            }
        }
    }
    Ok(())
}
<commit_msg>Fix keybinding emission<commit_after>use rlua::{self, Lua};
use wlroots::{key_events::KeyEvent, xkbcommon::xkb::{KEY_Escape, KEY_Super_L, KEY_Super_R},
              Capability, CompositorHandle, KeyboardHandle, KeyboardHandler, KeyboardModifier,
              WLR_KEY_PRESSED};

use awesome::{self, emit_object_signal, Objectable, LUA, ROOT_KEYS_HANDLE};
use compositor::Server;

pub struct Keyboard;

fn key_is_meta(key: u32) -> bool {
    // TODO configure meta key
    key == KEY_Super_L || key == KEY_Super_R
}

impl KeyboardHandler for Keyboard {
    fn on_key(&mut self, compositor: CompositorHandle, keyboard: KeyboardHandle, event: &KeyEvent) {
        let modifiers = dehandle!(
            @compositor = {compositor};
            if event.key_state() == WLR_KEY_PRESSED {
                for key in event.pressed_keys() {
                    if key == KEY_Escape {
                        // NOTE No need to call awesome::lua::terminate.
                        // that will be handled by wlroots.
                        ::wlroots::terminate();
                    }
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = true;
                    }
                }
            } else {
                for key in event.pressed_keys() {
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = false;
                    }
                }
            };
            let server: &mut Server = compositor.into();
            @seat = {&server.seat.seat};
            @keyboard = {keyboard};
            seat.set_keyboard(keyboard.input_device());
            seat.keyboard_notify_key(event.time_msec(),
                                        event.keycode(),
                                        event.key_state() as u32);
            seat.keyboard_send_modifiers(&mut keyboard.get_modifier_masks());
            keyboard.get_modifiers()
        );
        LUA.with(|lua| {
                     let lua = lua.borrow();
                     if let Err(err) = emit_awesome_keybindings(&*lua, event, modifiers) {
                         warn!("Could not emit binding for {}: {:?}", event.keycode(), err);
                     }
                 });
    }

    fn modifiers(&mut self, compositor: CompositorHandle, keyboard: KeyboardHandle) {
        dehandle!(
            @compositor = {compositor};
            let server: &mut Server = compositor.into();
            @seat = {&server.seat.seat};
            @keyboard = {keyboard};
            seat.keyboard_notify_modifiers(&mut keyboard.get_modifier_masks())
        );
    }

    fn destroyed(&mut self, compositor: CompositorHandle, keyboard: KeyboardHandle) {
        with_handles!([(compositor: {compositor}), (keyboard: {keyboard})] => {
            let server: &mut Server = compositor.into();
            let weak_reference = keyboard.weak_reference();
            if let Some(index) = server.keyboards.iter().position(|k| *k == weak_reference) {
                server.keyboards.remove(index);
                if server.keyboards.len() == 0 {
                    with_handles!([(seat: {&mut server.seat.seat})] => {
                        let mut capabilities = seat.capabilities();
                        capabilities.remove(Capability::Keyboard);
                        seat.set_capabilities(capabilities);
                    }).expect("Seat was destroyed")
                }
            }
        }).unwrap();
    }
}

/// Emits the Awesome keybindinsg.
fn emit_awesome_keybindings(lua: &Lua,
                            event: &KeyEvent,
                            event_modifiers: KeyboardModifier)
                            -> rlua::Result<()> {
    let state_string = if event.key_state() == WLR_KEY_PRESSED {
        "press"
    } else {
        "release"
    };
    // TODO Should also emit by current focused client so we can
    // do client based rules.
    let keybindings = lua.named_registry_value::<Vec<rlua::AnyUserData>>(ROOT_KEYS_HANDLE)?;
    for event_keysym in event.pressed_keys() {
        for binding in &keybindings {
            let obj: awesome::Object = binding.clone().into();
            let key = awesome::Key::cast(obj.clone()).unwrap();
            let keycode = key.keycode()?;
            let keysym = key.keysym()?;
            let modifiers = key.modifiers()?;
            let binding_match = ((keysym != 0 && keysym == event_keysym)
                                 || (keycode != 0 && keycode == event.keycode()))
                                && (modifiers == 0
                                || modifiers == event_modifiers.bits());
            if binding_match {
                emit_object_signal(&*lua, obj, state_string.into(), ())?;
            }
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//================================================
// Macros
//================================================

// link! _________________________________________

#[cfg(feature="runtime")]
macro_rules! link {
    (@LOAD: #[cfg($cfg:meta)] fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        #[cfg($cfg)]
        pub fn $name(library: &mut super::SharedLibrary) {
            let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
            library.functions.$name = symbol.map(|s| *s);
        }

        #[cfg(not($cfg))]
        pub fn $name(_: &mut super::SharedLibrary) {}
    );

    (@LOAD: fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        link!(@LOAD: #[cfg(feature="runtime")] fn $name($($pname: $pty), *) $(-> $ret)*);
    );

    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        use std::cell::{RefCell};
        use std::sync::{Arc};

        /// The set of functions loaded dynamically.
        #[derive(Debug)]
        pub struct Functions {
            $($(#[cfg($cfg)])* pub $name: Option<extern fn($($pname: $pty), *) $(-> $ret)*>,)+
        }

        impl Default for Functions {
            fn default() -> Functions {
                unsafe { std::mem::zeroed() }
            }
        }

        /// A dynamically loaded instance of the libclang library.
        #[derive(Debug)]
        pub struct SharedLibrary {
            library: libloading::Library,
            pub functions: Functions,
        }

        impl SharedLibrary {
            //- Constructors -----------------------------

            fn new(library: libloading::Library) -> SharedLibrary {
                SharedLibrary { library: library, functions: Functions::default() }
            }
        }

        thread_local!(static LIBRARY: RefCell<Option<Arc<SharedLibrary>>> = RefCell::new(None));

        /// Whether `libclang` is loaded on this thread.
        pub fn is_loaded() -> bool {
            LIBRARY.with(|l| l.borrow().is_some())
        }

        $(
            $(#[cfg($cfg)])* pub unsafe fn $name($($pname: $pty), *) $(-> $ret)* {
                let f = LIBRARY.with(|l| l.borrow().as_ref().map(|l| {
                    match l.functions.$name {
                        Some(f) => f,
                        None => panic!("Function not loaded: {}!", stringify!($name)),
                    }
                }));
                (f.expect("a `libclang` shared library was not loaded on this thread"))($($pname), *)
            }

            $(#[cfg($cfg)])* pub mod $name {
                use super::LIBRARY;
                pub fn is_loaded() -> bool {
                    LIBRARY.with(|l| l.borrow().as_ref().map_or(false, |l| {
                        l.functions.$name.is_some()
                    }))
                }
            }
        )+

        #[path="../build.rs"]
        mod build;

        mod load {
            $(link!(@LOAD: $(#[cfg($cfg)])* fn $name($($pname: $pty), *) $(-> $ret)*);)+
        }

        /// Loads a `libclang` shared library for use in the current thread.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library has already been loaded
        /// * a `libclang` shared library could not be found
        ///
        /// Note that this tries to find all the symbols. To check if a symbol
        /// has been found or not, you can use `clang_Foo::is_loaded()`.
        #[allow(dead_code)]
        pub fn load() -> Result<(), String> {
            let lib = Arc::new(try!(load_manually()));
            LIBRARY.with(|l| *l.borrow_mut() = Some(lib));
            Ok(())
        }

        /// Gets the library from tls. This, along with `set_library`, allows
        /// reusing the same library across threads.
        pub fn get_library() -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| {
                l.borrow_mut().clone()
            })
        }

        /// Sets the current library from tls, and returns the previous one.
        pub fn set_library(lib: Option<Arc<SharedLibrary>>) -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| {
                let mut l = l.borrow_mut();
                mem::replace(&mut *l, lib)
            })
        }

        /// Tries to load a libclang library manually, returning the
        /// corresponding `SharedLibrary`.
        ///
        /// Only returns an error when the library couldn't be found or opened,
        /// and the caller is responsible handle the functions manually.
        pub fn load_manually() -> Result<SharedLibrary, String> {
            let file = try!(build::find_shared_library());
            let library = libloading::Library::new(&file).map_err(|_| {
                format!("'{}' could not be opened", file.display())
            });
            let mut library = SharedLibrary::new(try!(library));
            $(load::$name(&mut library);)+

            Ok(library)
        }

        /// Unloads the `libclang` shared library in use in the current thread.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library is not in use in the current thread
        pub fn unload() -> Result<(), String> {
            let l = set_library(None);

            if l.is_some() {
                Ok(())
            } else {
                Err("a `libclang` shared library is not in use in the current thread".into())
            }
        }
    )
}

#[cfg(not(feature="runtime"))]
macro_rules! link {
    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        extern { $($(#[cfg($cfg)])* pub fn $name($($pname: $pty), *) $(-> $ret)*;)+ }
    )
}
<commit_msg>Refactor<commit_after>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//================================================
// Macros
//================================================

// link! _________________________________________

#[cfg(feature="runtime")]
macro_rules! link {
    (@LOAD: #[cfg($cfg:meta)] fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        #[cfg($cfg)]
        pub fn $name(library: &mut super::SharedLibrary) {
            let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
            library.functions.$name = symbol.map(|s| *s);
        }

        #[cfg(not($cfg))]
        pub fn $name(_: &mut super::SharedLibrary) {}
    );

    (@LOAD: fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        link!(@LOAD: #[cfg(feature="runtime")] fn $name($($pname: $pty), *) $(-> $ret)*);
    );

    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        use std::cell::{RefCell};
        use std::sync::{Arc};

        /// The set of functions loaded dynamically.
        #[derive(Debug)]
        pub struct Functions {
            $($(#[cfg($cfg)])* pub $name: Option<extern fn($($pname: $pty), *) $(-> $ret)*>,)+
        }

        impl Default for Functions {
            fn default() -> Functions {
                unsafe { std::mem::zeroed() }
            }
        }

        /// A dynamically loaded instance of the `libclang` library.
        #[derive(Debug)]
        pub struct SharedLibrary {
            library: libloading::Library,
            pub functions: Functions,
        }

        impl SharedLibrary {
            //- Constructors -----------------------------

            fn new(library: libloading::Library) -> SharedLibrary {
                SharedLibrary { library: library, functions: Functions::default() }
            }
        }

        thread_local!(static LIBRARY: RefCell<Option<Arc<SharedLibrary>>> = RefCell::new(None));

        /// Returns whether a `libclang` shared library is loaded on this thread.
        pub fn is_loaded() -> bool {
            LIBRARY.with(|l| l.borrow().is_some())
        }

        fn with_library<T, F>(f: F) -> Option<T> where F: FnOnce(&SharedLibrary) -> T {
            LIBRARY.with(|l| {
                match l.borrow().as_ref() {
                    Some(library) => Some(f(&library)),
                    _ => None,
                }
            })
        }

        $(
            $(#[cfg($cfg)])*
            pub unsafe fn $name($($pname: $pty), *) $(-> $ret)* {
                let f = with_library(|l| {
                    match l.functions.$name {
                        Some(f) => f,
                        _ => panic!(concat!("function not loaded: ", stringify!($name))),
                    }
                }).expect("a `libclang` shared library is not loaded on this thread");
                f($($pname), *)
            }

            $(#[cfg($cfg)])*
            pub mod $name {
                pub fn is_loaded() -> bool {
                    super::with_library(|l| l.functions.$name.is_some()).unwrap_or(false)
                }
            }
        )+

        mod load {
            $(link!(@LOAD: $(#[cfg($cfg)])* fn $name($($pname: $pty), *) $(-> $ret)*);)+
        }

        /// Loads a `libclang` shared library and returns the library instance.
        ///
        /// This function does not attempt to load any functions from the shared library. The caller
        /// is responsible for loading the functions they require.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library could not be found
        /// * the `libclang` shared library could not be opened
        pub fn load_manually() -> Result<SharedLibrary, String> {
            #[path="../build.rs"]
            mod build;

            let file = try!(build::find_shared_library());
            let library = libloading::Library::new(&file).map_err(|_| {
                format!("the `libclang` shared library could not be opened: {}", file.display())
            });
            let mut library = SharedLibrary::new(try!(library));
            $(load::$name(&mut library);)+
            Ok(library)
        }

        /// Loads a `libclang` shared library for use in the current thread.
        ///
        /// This functions attempts to load all the functions in the shared library. Whether a
        /// function has been loaded can be tested by calling the `is_loaded` function on the
        /// module with the same name as the function (e.g., `clang_createIndex::is_loaded()` for
        /// the `clang_createIndex` function).
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library could not be found
        /// * the `libclang` shared library could not be opened
        #[allow(dead_code)]
        pub fn load() -> Result<(), String> {
            let library = Arc::new(try!(load_manually()));
            LIBRARY.with(|l| *l.borrow_mut() = Some(library));
            Ok(())
        }

        /// Unloads the `libclang` shared library in use in the current thread.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library is not in use in the current thread
        pub fn unload() -> Result<(), String> {
            let library = set_library(None);
            if library.is_some() {
                Ok(())
            } else {
                Err("a `libclang` shared library is not in use in the current thread".into())
            }
        }

        /// Returns the library instance stored in TLS.
        ///
        /// This functions allows for sharing library instances between threads.
        pub fn get_library() -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| l.borrow_mut().clone())
        }

        /// Sets the library instance stored in TLS and returns the previous library.
        ///
        /// This functions allows for sharing library instances between threads.
        pub fn set_library(library: Option<Arc<SharedLibrary>>) -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| mem::replace(&mut *l.borrow_mut(), library))
        }
    )
}

#[cfg(not(feature="runtime"))]
macro_rules! link {
    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        extern { $($(#[cfg($cfg)])* pub fn $name($($pname: $pty), *) $(-> $ret)*;)+ }
    )
}
<|endoftext|>