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

//! Interface for the GPIO peripheral.
//!
//! To ensure fast performance, RPPAL interfaces with the GPIO peripheral by
//! directly accessing the registers through either `/dev/gpiomem` or `/dev/mem`.
//! GPIO interrupts are controlled using the `/dev/gpiochipN` (where N=0, 1 and 2)
//! character device.
//!
//! ## Pins
//!
//! Pins are addressed by their BCM numbers, rather than their
//! physical location.
//!
//! By default, pins are reset to their original state when they go out of scope.
//! Use [`InputPin::set_reset_on_drop(false)`], [`OutputPin::set_reset_on_drop(false)`]
//! or [`AltPin::set_reset_on_drop(false)`], respectively, to disable this behavior.
//! Note that `drop` methods aren't called when a program is abnormally terminated (for
//! instance when a SIGINT isn't caught).
//!
//! ## Examples
//!
//! Basic example:
//!
//! ```
//! use std::thread::sleep;
//! use std::time::Duration;
//!
//! use rppal::gpio::Gpio;
//!
//! # fn main() -> rppal::gpio::Result<()> {
//! let gpio = Gpio::new()?;
//! let mut pin = gpio.get(23).unwrap().into_output();
//!
//! pin.set_high();
//! sleep(Duration::from_secs(1));
//! pin.set_low();
//! # Ok(())
//! # }
//! ```
//!
//! Additional examples can be found in the [`examples`] directory.
//!
//! ## Troubleshooting
//!
//! ### Permission denied
//!
//! In recent releases of Raspbian (December 2017 or later), users that are part of the
//! `gpio` group (like the default `pi` user) can access `/dev/gpiomem` and
//! `/dev/gpiochipN` without needing additional permissions. If you encounter any
//! Permission Denied errors when creating a new [`Gpio`] instance, either the current
//! user isn't a member of the `gpio` group, or your Raspbian distribution isn't
//! up-to-date and doesn't automatically configure permissions for the above-mentioned
//! files. Updating Raspbian to the latest release should fix any permission issues.
//! Alternatively, although not recommended, you can run your application with superuser
//! privileges by using `sudo`.
//!
//! If you're unable to update Raspbian and its packages (namely `raspberrypi-sys-mods`) to
//! the latest available release, or updating hasn't fixed the issue, you might be able to
//! manually update your udev rules to set the appropriate permissions. More information
//! can be found at [raspberrypi/linux#1225] and [raspberrypi/linux#2289].
//!
//! [`examples`]: https://github.com/golemparts/rppal/tree/master/examples
//! [raspberrypi/linux#1225]: https://github.com/raspberrypi/linux/issues/1225
//! [raspberrypi/linux#2289]: https://github.com/raspberrypi/linux/issues/2289
//! [`Gpio`]: struct.Gpio.html
//! [`InputPin::set_reset_on_drop(false)`]: struct.InputPin.html#method.set_reset_on_drop
//! [`OutputPin::set_reset_on_drop(false)`]: struct.InputPin.html#method.set_reset_on_drop
//! [`AltPin::set_reset_on_drop(false)`]: struct.InputPin.html#method.set_reset_on_drop
//! [`Error::InstanceExists`]: enum.Error.html#variant.InstanceExists

use std::fmt;
use std::io;
use std::os::unix::io::AsRawFd;
use std::result;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex, Weak};
use std::time::Duration;

use lazy_static::lazy_static;
use quick_error::quick_error;

mod epoll;
mod interrupt;
mod ioctl;
mod mem;
mod pin;

pub use self::pin::{AltPin, InputPin, OutputPin, Pin};

quick_error! {
/// Errors that can occur when accessing the GPIO peripheral.
    #[derive(Debug)]
    pub enum Error {
/// Unknown model.
///
/// The Raspberry Pi model or SoC can't be identified. Support for
/// new models is usually added shortly after they are officially
/// announced and available to the public. Make sure you're using
/// the latest release of RPPAL.
///
/// You may also encounter this error if your Linux distribution
/// doesn't provide any of the common user-accessible system files
/// that are used to identify the model and SoC.
        UnknownModel { description("unknown Raspberry Pi model") }
/// Permission denied when opening `/dev/gpiomem`, `/dev/mem` or `/dev/gpiochipN` for
/// read/write access.
///
/// More information on possible causes for this error can be found [here].
///
/// [here]: index.html#permission-denied
        PermissionDenied { description("/dev/gpiomem, /dev/mem or /dev/gpiochipN insufficient permissions") }
/// IO error.
        Io(err: io::Error) { description(err.description()) from() }
/// Interrupt polling thread panicked.
        ThreadPanic { description("interrupt polling thread panicked") }
    }
}

/// Result type returned from methods that can have `rppal::gpio::Error`s.
pub type Result<T> = result::Result<T, Error>;

/// Pin modes.
#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(u8)]
pub enum Mode {
    Input = 0b000,
    Output = 0b001,
    Alt0 = 0b100,
    Alt1 = 0b101,
    Alt2 = 0b110,
    Alt3 = 0b111,
    Alt4 = 0b011,
    Alt5 = 0b010,
}

impl fmt::Display for Mode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Mode::Input => write!(f, "In"),
            Mode::Output => write!(f, "Out"),
            Mode::Alt0 => write!(f, "Alt0"),
            Mode::Alt1 => write!(f, "Alt1"),
            Mode::Alt2 => write!(f, "Alt2"),
            Mode::Alt3 => write!(f, "Alt3"),
            Mode::Alt4 => write!(f, "Alt4"),
            Mode::Alt5 => write!(f, "Alt5"),
        }
    }
}

/// Pin logic levels.
#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(u8)]
pub enum Level {
    Low = 0,
    High = 1,
}

impl fmt::Display for Level {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Level::Low => write!(f, "Low"),
            Level::High => write!(f, "High"),
        }
    }
}

/// Built-in pull-up/pull-down resistor states.
#[derive(Debug, PartialEq, Copy, Clone)]
pub(crate) enum PullUpDown {
    Off = 0b00,
    PullDown = 0b01,
    PullUp = 0b10,
}

impl fmt::Display for PullUpDown {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            PullUpDown::Off => write!(f, "Off"),
            PullUpDown::PullDown => write!(f, "PullDown"),
            PullUpDown::PullUp => write!(f, "PullUp"),
        }
    }
}

/// Interrupt trigger conditions.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Trigger {
    Disabled = 0,
    RisingEdge = 1,
    FallingEdge = 2,
    Both = 3,
}

impl fmt::Display for Trigger {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Trigger::Disabled => write!(f, "Disabled"),
            Trigger::RisingEdge => write!(f, "RisingEdge"),
            Trigger::FallingEdge => write!(f, "FallingEdge"),
            Trigger::Both => write!(f, "Both"),
        }
    }
}

// Store Gpio's state separately, so we can conveniently share it through
// a cloned Arc.
pub(crate) struct GpioState {
    gpio_mem: mem::GpioMem,
    cdev: std::fs::File,
    sync_interrupts: Mutex<interrupt::EventLoop>,
    pins_taken: [AtomicBool; pin::MAX],
}

impl fmt::Debug for GpioState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("EventLoop")
            .field("gpio_mem", &self.gpio_mem)
            .field("cdev", &self.cdev)
            .field("sync_interrupts", &self.sync_interrupts)
            .field("pins_taken", &format_args!("{{ .. }}"))
            .finish()
    }
}

// Share state between Gpio and Pin instances. GpioState is dropped after
// all Gpio and Pin instances go out of scope, guaranteeing we won't have
// any pins simultaneously using different EventLoop or GpioMem instances.
lazy_static! {
    static ref GPIO_STATE: Mutex<Weak<GpioState>> = Mutex::new(Weak::new());
}

/// Provides access to the Raspberry Pi's GPIO peripheral.
#[derive(Clone, Debug)]
pub struct Gpio {
    inner: Arc<GpioState>,
}

impl Gpio {
    /// Constructs a new `Gpio`.
    pub fn new() -> Result<Gpio> {
        let mut static_state = GPIO_STATE.lock().unwrap();

        // Create a strong reference if a GpioState instance already exists,
        // otherwise initialize it here so we can return any relevant errors.
        if let Some(ref state) = static_state.upgrade() {
            Ok(Gpio {
                inner: state.clone(),
            })
        } else {
            let gpio_mem = mem::GpioMem::open()?;
            let cdev = ioctl::find_gpiochip()?;
            let sync_interrupts =
                Mutex::new(interrupt::EventLoop::new(cdev.as_raw_fd(), pin::MAX)?);
            let pins_taken = init_array!(AtomicBool::new(false), pin::MAX);

            let gpio_state = Arc::new(GpioState {
                gpio_mem,
                cdev,
                sync_interrupts,
                pins_taken,
            });

            // Store a weak reference to our state. This gets dropped when
            // all Gpio and Pin instances go out of scope.
            *static_state = Arc::downgrade(&gpio_state);

            Ok(Gpio { inner: gpio_state })
        }
    }

    /// Returns a [`Pin`] for the specified GPIO pin number.
    ///
    /// Retrieving a GPIO pin using `get` grants exclusive access to the GPIO
    /// pin through an owned [`Pin`]. If the selected pin number is already
    /// in use, `get` returns `None`. After a [`Pin`] goes out of scope, it can be retrieved
    /// again using `get`.
    ///
    /// [`Pin`]: struct.Pin.html
    pub fn get(&self, pin: u8) -> Option<pin::Pin> {
        if pin as usize >= pin::MAX {
            return None;
        }

        // Returns true if the pin is currently taken, otherwise atomically sets
        // it to true here
        if self.inner.pins_taken[pin as usize].compare_and_swap(false, true, Ordering::SeqCst) {
            // Pin is currently taken
            None
        } else {
            // Return an owned Pin
            let pin_instance = pin::Pin::new(pin, self.inner.clone());

            Some(pin_instance)
        }
    }

    /// Blocks until an interrupt is triggered on any of the specified pins, or until a timeout occurs.
    ///
    /// This only works for pins that have been configured for synchronous interrupts using
    /// [`InputPin::set_interrupt`]. Asynchronous interrupt triggers are automatically polled on a separate thread.
    ///
    /// Calling `poll_interrupts` blocks any other calls to `poll_interrupts` or [`InputPin::poll_interrupt`] until
    /// it returns. If you need to poll multiple pins simultaneously on different threads, use
    /// asynchronous interrupts with [`InputPin::set_async_interrupt`] instead.
    ///
    /// If `reset` is set to `false`, returns immediately if an interrupt trigger event was cached in a
    /// previous call to [`InputPin::poll_interrupt`] or `poll_interrupts`.
    /// If `reset` is set to `true`, clears any cached interrupt trigger events before polling.
    ///
    /// The `timeout` duration indicates how long the call to `poll_interrupts` will block while waiting
    /// for interrupt trigger events, after which an `Ok(None)` is returned.
    /// `timeout` can be set to `None` to wait indefinitely.
    ///
    /// When an interrupt event is triggered, `poll_interrupts` returns
    /// `Ok((&`[`InputPin`]`, `[`Level`]`))` containing the corresponding pin and logic level. If multiple events trigger
    /// at the same time, only the first one is returned. The remaining events are cached and will be returned
    /// the next time [`InputPin::poll_interrupt`] or `poll_interrupts` is called.
    ///
    /// [`InputPin::set_interrupt`]: struct.InputPin#method.set_interrupt
    /// [`InputPin::poll_interrupt`]: struct.InputPin#method.poll_interrupt
    /// [`InputPin::set_async_interrupt`]: struct.InputPin#method.set_async_interrupt
    /// [`InputPin`]: struct.InputPin
    /// [`Level`]: struct.Level
    pub fn poll_interrupts<'a>(
        &self,
        pins: &[&'a InputPin],
        reset: bool,
        timeout: Option<Duration>,
    ) -> Result<Option<(&'a InputPin, Level)>> {
        (*self.inner.sync_interrupts.lock().unwrap()).poll(pins, reset, timeout)
    }
}
<commit_msg>Update documentation<commit_after>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! Interface for the GPIO peripheral.
//!
//! To ensure fast performance, RPPAL interfaces with the GPIO peripheral by
//! directly accessing the registers through either `/dev/gpiomem` or `/dev/mem`.
//! GPIO interrupts are controlled using the `/dev/gpiochipN` (where N=0, 1 and 2)
//! character device.
//!
//! ## Pins
//!
//! GPIO pins are retrieved from a [`Gpio`] instance by their BCM GPIO pin number through
//! [`Gpio::get`]. The returned unconfigured [`Pin`] can be used to read the pin's current
//! mode or logic level. Configuring the [`Pin`] as an [`InputPin`], [`OutputPin`] or
//! [`AltPin`] through the various `into_` methods available on [`Pin`] sets the
//! appropriate mode, and provides access to additional methods depending on the pin mode.
//!
//! Retrieving a pin with [`Gpio::get`] grants exclusive access through an owned [`Pin`]
//! instance. If the pin is already in use, [`Gpio::get`] returns `None`. After a [`Pin`]
//! (or a derived [`InputPin`], [`OutputPin`] or [`AltPin`]) goes out of scope, it can be
//! retrieved again through another [`Gpio::get`] call.
//!
//! By default, pins are reset to their original state when they go out of scope.
//! Use [`InputPin::set_reset_on_drop(false)`], [`OutputPin::set_reset_on_drop(false)`]
//! or [`AltPin::set_reset_on_drop(false)`], respectively, to disable this behavior.
//! Note that `drop` methods aren't called when a program is abnormally terminated (for
//! instance when a SIGINT isn't caught).
//!
//! ## Interrupts
//!
//! TODO: ...
//!
//! ## Examples
//!
//! Basic example:
//!
//! ```
//! use std::thread::sleep;
//! use std::time::Duration;
//!
//! use rppal::gpio::Gpio;
//!
//! # fn main() -> rppal::gpio::Result<()> {
//! let gpio = Gpio::new()?;
//! let mut pin = gpio.get(23).unwrap().into_output();
//!
//! pin.set_high();
//! sleep(Duration::from_secs(1));
//! pin.set_low();
//! # Ok(())
//! # }
//! ```
//!
//! Additional examples can be found in the [`examples`] directory.
//!
//! ## Troubleshooting
//!
//! ### Permission denied
//!
//! In recent releases of Raspbian (December 2017 or later), users that are part of the
//! `gpio` group (like the default `pi` user) can access `/dev/gpiomem` and
//! `/dev/gpiochipN` without needing additional permissions. If you encounter any
//! Permission Denied errors when creating a new [`Gpio`] instance, either the current
//! user isn't a member of the `gpio` group, or your Raspbian distribution isn't
//! up-to-date and doesn't automatically configure permissions for the above-mentioned
//! files. Updating Raspbian to the latest release should fix any permission issues.
//! Alternatively, although not recommended, you can run your application with superuser
//! privileges by using `sudo`.
//!
//! If you're unable to update Raspbian and its packages (namely `raspberrypi-sys-mods`) to
//! the latest available release, or updating hasn't fixed the issue, you might be able to
//! manually update your udev rules to set the appropriate permissions. More information
//! can be found at [raspberrypi/linux#1225] and [raspberrypi/linux#2289].
//!
//! [`examples`]: https://github.com/golemparts/rppal/tree/master/examples
//! [raspberrypi/linux#1225]: https://github.com/raspberrypi/linux/issues/1225
//! [raspberrypi/linux#2289]: https://github.com/raspberrypi/linux/issues/2289
//! [`Gpio`]: struct.Gpio.html
//! [`Gpio::get`]: struct.Gpio.html#method.get
//! [`Pin`]: struct.Pin.html
//! [`InputPin`]: struct.InputPin.html
//! [`InputPin::set_reset_on_drop(false)`]: struct.InputPin.html#method.set_reset_on_drop
//! [`OutputPin`]: struct.OutputPin.html
//! [`OutputPin::set_reset_on_drop(false)`]: struct.InputPin.html#method.set_reset_on_drop
//! [`AltPin`]: struct.AltPin.html
//! [`AltPin::set_reset_on_drop(false)`]: struct.InputPin.html#method.set_reset_on_drop
//! [`Error::InstanceExists`]: enum.Error.html#variant.InstanceExists

use std::fmt;
use std::io;
use std::os::unix::io::AsRawFd;
use std::result;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex, Weak};
use std::time::Duration;

use lazy_static::lazy_static;
use quick_error::quick_error;

mod epoll;
mod interrupt;
mod ioctl;
mod mem;
mod pin;

pub use self::pin::{AltPin, InputPin, OutputPin, Pin};

quick_error! {
/// Errors that can occur when accessing the GPIO peripheral.
    #[derive(Debug)]
    pub enum Error {
/// Unknown model.
///
/// The Raspberry Pi model or SoC can't be identified. Support for
/// new models is usually added shortly after they are officially
/// announced and available to the public. Make sure you're using
/// the latest release of RPPAL.
///
/// You may also encounter this error if your Linux distribution
/// doesn't provide any of the common user-accessible system files
/// that are used to identify the model and SoC.
        UnknownModel { description("unknown Raspberry Pi model") }
/// Permission denied when opening `/dev/gpiomem`, `/dev/mem` or `/dev/gpiochipN` for
/// read/write access.
///
/// More information on possible causes for this error can be found [here].
///
/// [here]: index.html#permission-denied
        PermissionDenied { description("/dev/gpiomem, /dev/mem or /dev/gpiochipN insufficient permissions") }
/// IO error.
        Io(err: io::Error) { description(err.description()) from() }
/// Interrupt polling thread panicked.
        ThreadPanic { description("interrupt polling thread panicked") }
    }
}

/// Result type returned from methods that can have `rppal::gpio::Error`s.
pub type Result<T> = result::Result<T, Error>;

/// Pin modes.
#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(u8)]
pub enum Mode {
    Input = 0b000,
    Output = 0b001,
    Alt0 = 0b100,
    Alt1 = 0b101,
    Alt2 = 0b110,
    Alt3 = 0b111,
    Alt4 = 0b011,
    Alt5 = 0b010,
}

impl fmt::Display for Mode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Mode::Input => write!(f, "In"),
            Mode::Output => write!(f, "Out"),
            Mode::Alt0 => write!(f, "Alt0"),
            Mode::Alt1 => write!(f, "Alt1"),
            Mode::Alt2 => write!(f, "Alt2"),
            Mode::Alt3 => write!(f, "Alt3"),
            Mode::Alt4 => write!(f, "Alt4"),
            Mode::Alt5 => write!(f, "Alt5"),
        }
    }
}

/// Pin logic levels.
#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(u8)]
pub enum Level {
    Low = 0,
    High = 1,
}

impl fmt::Display for Level {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Level::Low => write!(f, "Low"),
            Level::High => write!(f, "High"),
        }
    }
}

/// Built-in pull-up/pull-down resistor states.
#[derive(Debug, PartialEq, Copy, Clone)]
pub(crate) enum PullUpDown {
    Off = 0b00,
    PullDown = 0b01,
    PullUp = 0b10,
}

impl fmt::Display for PullUpDown {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            PullUpDown::Off => write!(f, "Off"),
            PullUpDown::PullDown => write!(f, "PullDown"),
            PullUpDown::PullUp => write!(f, "PullUp"),
        }
    }
}

/// Interrupt trigger conditions.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Trigger {
    Disabled = 0,
    RisingEdge = 1,
    FallingEdge = 2,
    Both = 3,
}

impl fmt::Display for Trigger {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Trigger::Disabled => write!(f, "Disabled"),
            Trigger::RisingEdge => write!(f, "RisingEdge"),
            Trigger::FallingEdge => write!(f, "FallingEdge"),
            Trigger::Both => write!(f, "Both"),
        }
    }
}

// Store Gpio's state separately, so we can conveniently share it through
// a cloned Arc.
pub(crate) struct GpioState {
    gpio_mem: mem::GpioMem,
    cdev: std::fs::File,
    sync_interrupts: Mutex<interrupt::EventLoop>,
    pins_taken: [AtomicBool; pin::MAX],
}

impl fmt::Debug for GpioState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("EventLoop")
            .field("gpio_mem", &self.gpio_mem)
            .field("cdev", &self.cdev)
            .field("sync_interrupts", &self.sync_interrupts)
            .field("pins_taken", &format_args!("{{ .. }}"))
            .finish()
    }
}

// Share state between Gpio and Pin instances. GpioState is dropped after
// all Gpio and Pin instances go out of scope, guaranteeing we won't have
// any pins simultaneously using different EventLoop or GpioMem instances.
lazy_static! {
    static ref GPIO_STATE: Mutex<Weak<GpioState>> = Mutex::new(Weak::new());
}

/// Provides access to the Raspberry Pi's GPIO peripheral.
#[derive(Clone, Debug)]
pub struct Gpio {
    inner: Arc<GpioState>,
}

impl Gpio {
    /// Constructs a new `Gpio`.
    pub fn new() -> Result<Gpio> {
        let mut static_state = GPIO_STATE.lock().unwrap();

        // Create a strong reference if a GpioState instance already exists,
        // otherwise initialize it here so we can return any relevant errors.
        if let Some(ref state) = static_state.upgrade() {
            Ok(Gpio {
                inner: state.clone(),
            })
        } else {
            let gpio_mem = mem::GpioMem::open()?;
            let cdev = ioctl::find_gpiochip()?;
            let sync_interrupts =
                Mutex::new(interrupt::EventLoop::new(cdev.as_raw_fd(), pin::MAX)?);
            let pins_taken = init_array!(AtomicBool::new(false), pin::MAX);

            let gpio_state = Arc::new(GpioState {
                gpio_mem,
                cdev,
                sync_interrupts,
                pins_taken,
            });

            // Store a weak reference to our state. This gets dropped when
            // all Gpio and Pin instances go out of scope.
            *static_state = Arc::downgrade(&gpio_state);

            Ok(Gpio { inner: gpio_state })
        }
    }

    /// Returns a [`Pin`] for the specified BCM GPIO pin number.
    ///
    /// Retrieving a pin grants exclusive access through an owned [`Pin`] instance. If the
    /// pin is already in use, `get` returns `None`. After a [`Pin`] (or a derived
    /// [`InputPin`], [`OutputPin`] or [`AltPin`]) goes out of scope, it can be retrieved
    /// again through another `get` call.
    ///
    /// [`Pin`]: struct.Pin.html
    /// [`InputPin`]: struct.InputPin.html
    /// [`OutputPin`]: struct.OutputPin.html
    /// [`AltPin`]: struct.AltPin.html
    pub fn get(&self, pin: u8) -> Option<pin::Pin> {
        if pin as usize >= pin::MAX {
            return None;
        }

        // Returns true if the pin is currently taken, otherwise atomically sets
        // it to true here
        if self.inner.pins_taken[pin as usize].compare_and_swap(false, true, Ordering::SeqCst) {
            // Pin is currently taken
            None
        } else {
            // Return an owned Pin
            let pin_instance = pin::Pin::new(pin, self.inner.clone());

            Some(pin_instance)
        }
    }

    /// Blocks until an interrupt is triggered on any of the specified pins, or until a timeout occurs.
    ///
    /// This only works for pins that have been configured for synchronous interrupts using
    /// [`InputPin::set_interrupt`]. Asynchronous interrupt triggers are automatically polled on a separate thread.
    ///
    /// Calling `poll_interrupts` blocks any other calls to `poll_interrupts` or [`InputPin::poll_interrupt`] until
    /// it returns. If you need to poll multiple pins simultaneously on different threads, use
    /// asynchronous interrupts with [`InputPin::set_async_interrupt`] instead.
    ///
    /// If `reset` is set to `false`, returns immediately if an interrupt trigger event was cached in a
    /// previous call to [`InputPin::poll_interrupt`] or `poll_interrupts`.
    /// If `reset` is set to `true`, clears any cached interrupt trigger events before polling.
    ///
    /// The `timeout` duration indicates how long the call to `poll_interrupts` will block while waiting
    /// for interrupt trigger events, after which an `Ok(None)` is returned.
    /// `timeout` can be set to `None` to wait indefinitely.
    ///
    /// When an interrupt event is triggered, `poll_interrupts` returns
    /// `Ok((&`[`InputPin`]`, `[`Level`]`))` containing the corresponding pin and logic level. If multiple events trigger
    /// at the same time, only the first one is returned. The remaining events are cached and will be returned
    /// the next time [`InputPin::poll_interrupt`] or `poll_interrupts` is called.
    ///
    /// [`InputPin::set_interrupt`]: struct.InputPin#method.set_interrupt
    /// [`InputPin::poll_interrupt`]: struct.InputPin#method.poll_interrupt
    /// [`InputPin::set_async_interrupt`]: struct.InputPin#method.set_async_interrupt
    /// [`InputPin`]: struct.InputPin
    /// [`Level`]: struct.Level
    pub fn poll_interrupts<'a>(
        &self,
        pins: &[&'a InputPin],
        reset: bool,
        timeout: Option<Duration>,
    ) -> Result<Option<(&'a InputPin, Level)>> {
        (*self.inner.sync_interrupts.lock().unwrap()).poll(pins, reset, timeout)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2017 Intecture Developers.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

#[macro_use] extern crate quote;
extern crate proc_macro;
extern crate syn;

use quote::Ident;
use proc_macro::TokenStream;
use syn::{Lit, MetaItem};

#[proc_macro_derive(FromMessage)]
pub fn from_message(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();
    let gen = impl_from_message(&ast);
    gen.parse().unwrap()
}

fn impl_from_message(ast: &syn::DeriveInput) -> quote::Tokens {
    let name = &ast.ident;

    quote! {
        impl FromMessage for #name {
            fn from_msg(msg: InMessage) -> Result<Self> {
                Ok(json::from_value(msg.into_inner())?)
            }
        }
    }
}

#[proc_macro_derive(IntoMessage, attributes(request))]
pub fn into_message(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();
    let gen = impl_into_message(&ast);
    gen.parse().unwrap()
}

fn impl_into_message(ast: &syn::DeriveInput) -> quote::Tokens {
    let name = &ast.ident;
    let mut req_attr = None;

    for attr in &ast.attrs {
        match attr.value {
            MetaItem::NameValue(ref i, Lit::Str(ref v, _)) if i == "request" => req_attr = Some(v.to_string()),
            _ => (),
        }
    }

    let request = Ident::new(req_attr.expect("Missing `request` attribute"));

    quote! {
        impl IntoMessage for #name {
            fn into_msg(self, handle: &Handle) -> Result<InMessage> {
                Request::#request(self).into_msg(handle)
            }
        }
    }
}
<commit_msg>Handle generics and where clauses in derive<commit_after>// Copyright 2015-2017 Intecture Developers.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

#[macro_use] extern crate quote;
extern crate proc_macro;
extern crate syn;

use quote::Ident;
use proc_macro::TokenStream;
use syn::{Lit, MetaItem};

#[proc_macro_derive(FromMessage)]
pub fn from_message(input: TokenStream) -> TokenStream {
    let ast = syn::parse_derive_input(&input.to_string()).unwrap();
    let gen = impl_from_message(&ast);
    gen.parse().unwrap()
}

fn impl_from_message(ast: &syn::DeriveInput) -> quote::Tokens {
    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

    quote! {
        impl #impl_generics FromMessage for #name #ty_generics #where_clause {
            fn from_msg(msg: InMessage) -> Result<Self> {
                Ok(json::from_value(msg.into_inner())?)
            }
        }
    }
}

#[proc_macro_derive(IntoMessage, attributes(request))]
pub fn into_message(input: TokenStream) -> TokenStream {
    let ast = syn::parse_derive_input(&input.to_string()).unwrap();
    let gen = impl_into_message(&ast);
    gen.parse().unwrap()
}

fn impl_into_message(ast: &syn::DeriveInput) -> quote::Tokens {
    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
    let mut req_attr = None;

    for attr in &ast.attrs {
        match attr.value {
            MetaItem::NameValue(ref i, Lit::Str(ref v, _)) if i == "request" => req_attr = Some(v.to_string()),
            _ => (),
        }
    }

    let request = Ident::new(req_attr.expect("Missing `request` attribute"));

    quote! {
        impl #impl_generics IntoMessage for #name #ty_generics #where_clause {
            fn into_msg(self, handle: &Handle) -> Result<InMessage> {
                Request::#request(self).into_msg(handle)
            }
        }
    }
}
<|endoftext|>


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

extern crate num;

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

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

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

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

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

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

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

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

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

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

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

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

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

ger_impl!(Gerc, gerc, Complex32, cblas_cgerc)
ger_impl!(Gerc, gerc, Complex64, cblas_zgerc)

pub trait Her {
    fn her(symmetry: Symmetry, alpha: Self, x: &BlasVector<Complex<Self>>, a: &mut BlasMatrix<Complex<Self>>);
}

macro_rules! her_impl(
    ($t: ty, $her_fn: ident) => (
        impl Her for $t {
            fn her(symmetry: Symmetry, alpha: $t, x: &BlasVector<Complex<$t>>, a: &mut BlasMatrix<Complex<$t>>) {
                unsafe {
                    matrix_vector::ll::$her_fn(a.order(), symmetry,
                        a.rows(),
                        alpha,
                        x.as_ptr().as_c_ptr(), x.inc(),
                        a.as_mut_ptr().as_c_ptr(), a.lead_dim());
                }
            }
        }
    );
)

her_impl!(f32, cblas_cher)
her_impl!(f64, cblas_zher)

pub trait Syr {
    fn syr(symmetry: Symmetry, alpha: Self, x: &BlasVector<Self>, a: &mut BlasMatrix<Self>);
}

macro_rules! syr_impl(
    ($t: ty, $syr_fn: ident) => (
        impl Syr for $t {
            fn syr(symmetry: Symmetry, alpha: $t, x: &BlasVector<$t>, a: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix_vector::ll::$syr_fn(a.order(), symmetry,
                        a.rows(),
                        alpha,
                        x.as_ptr().as_c_ptr(), x.inc(),
                        a.as_mut_ptr().as_c_ptr(), a.lead_dim());
                }
            }
        }
    );
)

syr_impl!(f32, cblas_ssyr)
syr_impl!(f64, cblas_dsyr)
<commit_msg>Add Syr2 and Her2 traits<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

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

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

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

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

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

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

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

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

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

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

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

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

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

ger_impl!(Gerc, gerc, Complex32, cblas_cgerc)
ger_impl!(Gerc, gerc, Complex64, cblas_zgerc)

pub trait Her {
    fn her(symmetry: Symmetry, alpha: Self, x: &BlasVector<Complex<Self>>, a: &mut BlasMatrix<Complex<Self>>);
}

macro_rules! her_impl(
    ($t: ty, $her_fn: ident) => (
        impl Her for $t {
            fn her(symmetry: Symmetry, alpha: $t, x: &BlasVector<Complex<$t>>, a: &mut BlasMatrix<Complex<$t>>) {
                unsafe {
                    matrix_vector::ll::$her_fn(a.order(), symmetry,
                        a.rows(),
                        alpha,
                        x.as_ptr().as_c_ptr(), x.inc(),
                        a.as_mut_ptr().as_c_ptr(), a.lead_dim());
                }
            }
        }
    );
)

her_impl!(f32, cblas_cher)
her_impl!(f64, cblas_zher)

pub trait Syr {
    fn syr(symmetry: Symmetry, alpha: Self, x: &BlasVector<Self>, a: &mut BlasMatrix<Self>);
}

macro_rules! syr_impl(
    ($t: ty, $syr_fn: ident) => (
        impl Syr for $t {
            fn syr(symmetry: Symmetry, alpha: $t, x: &BlasVector<$t>, a: &mut BlasMatrix<$t>) {
                unsafe {
                    matrix_vector::ll::$syr_fn(a.order(), symmetry,
                        a.rows(),
                        alpha,
                        x.as_ptr().as_c_ptr(), x.inc(),
                        a.as_mut_ptr().as_c_ptr(), a.lead_dim());
                }
            }
        }
    );
)

syr_impl!(f32, cblas_ssyr)
syr_impl!(f64, cblas_dsyr)

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

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

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

syr2_impl!(Syr2, syr2, f32, cblas_ssyr2)
syr2_impl!(Syr2, syr2, f64, cblas_dsyr2)

syr2_impl!(Her2, her2, Complex32, cblas_cher2)
syr2_impl!(Her2, her2, Complex64, cblas_zher2)
<|endoftext|>


<commit_before>use super::Sexp;
use super::Atom;
use super::token::Token;

#[cfg(test)]
use super::token::Tokenizer;

#[derive(Debug, PartialEq)]
pub enum ParseError<'a> {
    UnexpectedToken(Token<'a>),
    UnexpectedEnd,
}

// Returns either the successfully parsed expression, or
// the invalid token which was not expected.
pub fn parse_sexp<'a, I>(tokenstream: &mut I) -> Result<Sexp, ParseError<'a>>
    where I: Iterator<Item = Token<'a>>
{
    match tokenstream.next() {
        None => Err(ParseError::UnexpectedEnd),
        Some(tok) => {
            match tok {
                Token::Str(s) => Ok(Sexp::from(s)),
                Token::QStr(s) => Ok(Sexp::from(s)),
                Token::UInt(u) => Ok(Sexp::from(Atom::UInt(u))),
                Token::SInt(s) => Ok(Sexp::from(Atom::SInt(s))),
                Token::Float(s) => Ok(Sexp::from(Atom::Float(s))),
                Token::OpenBrace => {
                    let mut exprs = vec![];
                    loop {
                        match parse_sexp(tokenstream) {
                            Ok(ex) => exprs.push(ex),
                            Err(ParseError::UnexpectedToken(Token::CloseBrace)) => break,
                            Err(err) => return Err(err),
                        }
                    }
                    Ok(Sexp::Tuple(exprs))
                }
                Token::OpenBracket => {
                    let mut exprs = vec![];
                    loop {
                        match parse_sexp(tokenstream) {
                            Ok(ex) => exprs.push(ex),
                            Err(ParseError::UnexpectedToken(Token::CloseBracket)) => break,
                            Err(err) => return Err(err),
                        }
                    }
                    Ok(Sexp::Array(exprs))
                }
                Token::OpenCurly => {
                    let mut exprs = vec![];
                    loop {
                        match parse_sexp(tokenstream) {
                            Ok(key) => {
                                match parse_sexp(tokenstream) {
                                    Ok(value) => {
                                        exprs.push((key, value));
                                    }
                                    Err(err) => return Err(err),
                                }
                            }
                            Err(ParseError::UnexpectedToken(Token::CloseCurly)) => break,
                            Err(err) => return Err(err),
                        }
                    }
                    Ok(Sexp::Map(exprs))
                }
                tok => Err(ParseError::UnexpectedToken(tok)),
            }
        }
    }
}

pub fn at_end<'a, I>(tokenstream: &mut I) -> bool
    where I: Iterator<Item = Token<'a>>
{
    tokenstream.next().is_none()
}

#[test]
fn test_parse_sexp() {
    let mut p = Tokenizer::new("123.45", true);
    assert_eq!(Ok(Sexp::from(123.45)), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("123", true);
    assert_eq!(Ok(Sexp::from(123usize)), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("+123", true);
    assert_eq!(Ok(Sexp::from(123isize)), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("\"hal\\\"lo\"", true);
    assert_eq!(Ok(Sexp::from("hal\"lo")), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("(123)", true);
    assert_eq!(Ok(Sexp::from((123usize,))), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("(test 123)   ", true);
    assert_eq!(Ok(Sexp::from(("test", 123usize))), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("(test 123)   123", true);
    assert_eq!(Ok(Sexp::from(("test", 123usize))), parse_sexp(&mut p));
    assert_eq!(false, at_end(&mut p));

    let mut p = Tokenizer::new("   ", true);
    assert_eq!(Err(ParseError::UnexpectedEnd), parse_sexp(&mut p));

    let mut p = Tokenizer::new("(abc    ", true);
    assert_eq!(Err(ParseError::UnexpectedEnd), parse_sexp(&mut p));

    let mut p = Tokenizer::new("(abc  }  ", true);
    assert_eq!(Err(ParseError::UnexpectedToken(Token::CloseCurly)),
               parse_sexp(&mut p));

    let mut p = Tokenizer::new("[1 2 3]", true);
    assert_eq!(Ok(Sexp::Array(vec![Sexp::from(1usize), Sexp::from(2usize), Sexp::from(3usize)])),
               parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("{a 1 b 2}", true);
    assert_eq!(Ok(Sexp::Map(vec![(Sexp::from("a"), Sexp::from(1usize)),
                                 (Sexp::from("b"), Sexp::from(2usize))])),
               parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("{a 1 b }", true);
    assert_eq!(Err(ParseError::UnexpectedToken(Token::CloseCurly)),
               parse_sexp(&mut p));
}
<commit_msg>Remove whitespace<commit_after>use super::Sexp;
use super::Atom;
use super::token::Token;

#[cfg(test)]
use super::token::Tokenizer;

#[derive(Debug, PartialEq)]
pub enum ParseError<'a> {
    UnexpectedToken(Token<'a>),
    UnexpectedEnd,
}

// Returns either the successfully parsed expression, or
// the invalid token which was not expected.
pub fn parse_sexp<'a, I>(tokenstream: &mut I) -> Result<Sexp, ParseError<'a>>
    where I: Iterator<Item = Token<'a>>
{
    match tokenstream.next() {
        None => Err(ParseError::UnexpectedEnd),
        Some(tok) => {
            match tok {
                Token::Str(s) => Ok(Sexp::from(s)),
                Token::QStr(s) => Ok(Sexp::from(s)),
                Token::UInt(u) => Ok(Sexp::from(Atom::UInt(u))),
                Token::SInt(s) => Ok(Sexp::from(Atom::SInt(s))),
                Token::Float(s) => Ok(Sexp::from(Atom::Float(s))),
                Token::OpenBrace => {
                    let mut exprs = vec![];
                    loop {
                        match parse_sexp(tokenstream) {
                            Ok(ex) => exprs.push(ex),
                            Err(ParseError::UnexpectedToken(Token::CloseBrace)) => break,
                            Err(err) => return Err(err),
                        }
                    }
                    Ok(Sexp::Tuple(exprs))
                }
                Token::OpenBracket => {
                    let mut exprs = vec![];
                    loop {
                        match parse_sexp(tokenstream) {
                            Ok(ex) => exprs.push(ex),
                            Err(ParseError::UnexpectedToken(Token::CloseBracket)) => break,
                            Err(err) => return Err(err),
                        }
                    }
                    Ok(Sexp::Array(exprs))
                }
                Token::OpenCurly => {
                    let mut exprs = vec![];
                    loop {
                        match parse_sexp(tokenstream) {
                            Ok(key) => {
                                match parse_sexp(tokenstream) {
                                    Ok(value) => {
                                        exprs.push((key, value));
                                    }
                                    Err(err) => return Err(err),
                                }
                            }
                            Err(ParseError::UnexpectedToken(Token::CloseCurly)) => break,
                            Err(err) => return Err(err),
                        }
                    }
                    Ok(Sexp::Map(exprs))
                }
                tok => Err(ParseError::UnexpectedToken(tok)),
            }
        }
    }
}

pub fn at_end<'a, I>(tokenstream: &mut I) -> bool
    where I: Iterator<Item = Token<'a>>
{
    tokenstream.next().is_none()
}

#[test]
fn test_parse_sexp() {
    let mut p = Tokenizer::new("123.45", true);
    assert_eq!(Ok(Sexp::from(123.45)), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("123", true);
    assert_eq!(Ok(Sexp::from(123usize)), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("+123", true);
    assert_eq!(Ok(Sexp::from(123isize)), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("\"hal\\\"lo\"", true);
    assert_eq!(Ok(Sexp::from("hal\"lo")), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("(123)", true);
    assert_eq!(Ok(Sexp::from((123usize,))), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("(test 123)   ", true);
    assert_eq!(Ok(Sexp::from(("test", 123usize))), parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("(test 123)   123", true);
    assert_eq!(Ok(Sexp::from(("test", 123usize))), parse_sexp(&mut p));
    assert_eq!(false, at_end(&mut p));

    let mut p = Tokenizer::new("   ", true);
    assert_eq!(Err(ParseError::UnexpectedEnd), parse_sexp(&mut p));

    let mut p = Tokenizer::new("(abc    ", true);
    assert_eq!(Err(ParseError::UnexpectedEnd), parse_sexp(&mut p));

    let mut p = Tokenizer::new("(abc  }  ", true);
    assert_eq!(Err(ParseError::UnexpectedToken(Token::CloseCurly)),
               parse_sexp(&mut p));

    let mut p = Tokenizer::new("[1 2 3]", true);
    assert_eq!(Ok(Sexp::Array(vec![Sexp::from(1usize), Sexp::from(2usize), Sexp::from(3usize)])),
               parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("{a 1 b 2}", true);
    assert_eq!(Ok(Sexp::Map(vec![(Sexp::from("a"), Sexp::from(1usize)),
                                 (Sexp::from("b"), Sexp::from(2usize))])),
               parse_sexp(&mut p));
    assert_eq!(true, at_end(&mut p));

    let mut p = Tokenizer::new("{a 1 b }", true);
    assert_eq!(Err(ParseError::UnexpectedToken(Token::CloseCurly)),
               parse_sexp(&mut p));
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use lexer::{Token, Tokens};
use error::ParserError;

type Operators = HashMap<&'static str, Operator>;

#[derive(PartialEq, Debug)]
enum Associativity {
    LeftToRight,
    RightToLeft,
}

#[derive(PartialEq, Debug)]
struct Operator(usize, Associativity);

impl Operator {
    fn new(precedence: usize, associativity: Associativity) -> Operator {
        Operator(precedence, associativity)
    }
}

pub struct Parser {
    operators: Operators,
}

impl Parser {
    fn new() -> Parser {
        Parser { operators: Operators::new() }
    }

    fn lower_precedence(&self, new_token: &Token, top_token: &Token) -> bool {
        let &Operator(new_token_prec, ref new_token_assoc) = match *new_token {
            Token::Operator(ref new_token_name) => {
                self.operators.get::<str>(&new_token_name).unwrap()
            }
            _ => unreachable!(),
        };

        let &Operator(top_token_prec, _) = match *top_token {
            Token::Operator(ref top_token_name) => {
                self.operators.get::<str>(&top_token_name).unwrap()
            }
            _ => unreachable!(),
        };

        (*new_token_assoc == Associativity::LeftToRight && new_token_prec > top_token_prec) ||
        (*new_token_assoc == Associativity::RightToLeft && new_token_prec >= top_token_prec)
    }

    pub fn parse(&mut self, tokens: Tokens) -> Result<Tokens, ParserError> {
        let mut stack = Tokens::new();
        let mut output = Tokens::new();

        let mut token_iterator = tokens.iter().peekable();
        while let Some(&(position, ref token)) = token_iterator.next() {
            match *token {
                Token::Decimal(_) => output.push((position, token.clone())),
                Token::Operator(ref name) => {
                    if !self.operators.contains_key::<str>(&name) {
                        return Err(ParserError::IllegalOperator(position));
                    }

                    loop {
                        match stack.last() {
                            Some(&(_, Token::Operator(_))) => {
                                if self.lower_precedence(&token, &stack.last().unwrap().1) {
                                    output.push(stack.pop().unwrap());
                                } else {
                                    break;
                                }
                            }
                            _ => break,
                        }
                    }

                    stack.push((position, token.clone()));
                }
                Token::OpenBracket => stack.push((position, token.clone())),
                Token::CloseBracket => {
                    let mut found = false;

                    loop {
                        match stack.last() {
                            Some(&(_, Token::OpenBracket)) => {
                                found = true;
                                stack.pop();
                                break;
                            }
                            None => break,
                            _ => output.push(stack.pop().unwrap()),
                        }
                    }
                    if !found {
                        return Err(ParserError::MissingOpeningBracket(position));
                    }
                }
                Token::Unknown(_) => {
                    return Err(ParserError::IllegalOperator(position));
                }
                _ => continue,

            }
        }
        loop {
            match stack.last() {
                Some(&(position, Token::OpenBracket)) => {
                    return Err(ParserError::MissingClosingBracket(position))
                }
                Some(_) => output.push(stack.pop().unwrap()),
                None => break,
            }
        }

        Ok(output)
    }
}

impl Default for Parser {
    fn default() -> Parser {
        let mut parser = Parser::new();

        parser.operators.insert("~", Operator::new(2, Associativity::RightToLeft));
        parser.operators.insert(">>", Operator::new(3, Associativity::LeftToRight));
        parser.operators.insert("<<", Operator::new(3, Associativity::LeftToRight));
        parser.operators.insert("&", Operator::new(4, Associativity::LeftToRight));
        parser.operators.insert("^", Operator::new(5, Associativity::LeftToRight));
        parser.operators.insert("|", Operator::new(6, Associativity::LeftToRight));

        parser
    }
}
<commit_msg>Remove peekable from token_iterator<commit_after>use std::collections::HashMap;
use lexer::{Token, Tokens};
use error::ParserError;

type Operators = HashMap<&'static str, Operator>;

#[derive(PartialEq, Debug)]
enum Associativity {
    LeftToRight,
    RightToLeft,
}

#[derive(PartialEq, Debug)]
struct Operator(usize, Associativity);

impl Operator {
    fn new(precedence: usize, associativity: Associativity) -> Operator {
        Operator(precedence, associativity)
    }
}

pub struct Parser {
    operators: Operators,
}

impl Parser {
    fn new() -> Parser {
        Parser { operators: Operators::new() }
    }

    fn lower_precedence(&self, new_token: &Token, top_token: &Token) -> bool {
        let &Operator(new_token_prec, ref new_token_assoc) = match *new_token {
            Token::Operator(ref new_token_name) => {
                self.operators.get::<str>(&new_token_name).unwrap()
            }
            _ => unreachable!(),
        };

        let &Operator(top_token_prec, _) = match *top_token {
            Token::Operator(ref top_token_name) => {
                self.operators.get::<str>(&top_token_name).unwrap()
            }
            _ => unreachable!(),
        };

        (*new_token_assoc == Associativity::LeftToRight && new_token_prec > top_token_prec) ||
        (*new_token_assoc == Associativity::RightToLeft && new_token_prec >= top_token_prec)
    }

    pub fn parse(&mut self, tokens: Tokens) -> Result<Tokens, ParserError> {
        let mut stack = Tokens::new();
        let mut output = Tokens::new();

        let mut token_iterator = tokens.iter();
        while let Some(&(position, ref token)) = token_iterator.next() {
            match *token {
                Token::Decimal(_) => output.push((position, token.clone())),
                Token::Operator(ref name) => {
                    if !self.operators.contains_key::<str>(&name) {
                        return Err(ParserError::IllegalOperator(position));
                    }

                    loop {
                        match stack.last() {
                            Some(&(_, Token::Operator(_))) => {
                                if self.lower_precedence(&token, &stack.last().unwrap().1) {
                                    output.push(stack.pop().unwrap());
                                } else {
                                    break;
                                }
                            }
                            _ => break,
                        }
                    }

                    stack.push((position, token.clone()));
                }
                Token::OpenBracket => stack.push((position, token.clone())),
                Token::CloseBracket => {
                    let mut found = false;

                    loop {
                        match stack.last() {
                            Some(&(_, Token::OpenBracket)) => {
                                found = true;
                                stack.pop();
                                break;
                            }
                            None => break,
                            _ => output.push(stack.pop().unwrap()),
                        }
                    }
                    if !found {
                        return Err(ParserError::MissingOpeningBracket(position));
                    }
                }
                Token::Unknown(_) => {
                    return Err(ParserError::IllegalOperator(position));
                }
                _ => continue,

            }
        }
        loop {
            match stack.last() {
                Some(&(position, Token::OpenBracket)) => {
                    return Err(ParserError::MissingClosingBracket(position))
                }
                Some(_) => output.push(stack.pop().unwrap()),
                None => break,
            }
        }

        Ok(output)
    }
}

impl Default for Parser {
    fn default() -> Parser {
        let mut parser = Parser::new();

        parser.operators.insert("~", Operator::new(2, Associativity::RightToLeft));
        parser.operators.insert(">>", Operator::new(3, Associativity::LeftToRight));
        parser.operators.insert("<<", Operator::new(3, Associativity::LeftToRight));
        parser.operators.insert("&", Operator::new(4, Associativity::LeftToRight));
        parser.operators.insert("^", Operator::new(5, Associativity::LeftToRight));
        parser.operators.insert("|", Operator::new(6, Associativity::LeftToRight));

        parser
    }
}
<|endoftext|>


<commit_before>use oak_runtime::stream::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

use ast::PNode;

grammar! bailey {
    use ast::PNode;
    use ast::Node::*;
    use ast::BinOp;
    use ast::BinOp::*;
    use std::str::FromStr;

    program
        = (newlines stmt_or_decl terminator)*

    stmt_or_decl
        = stmt
        / decl

    decl
        = class_decl
        / method_decl

    class_decl
        = class_kw constant class_body > class_decl

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = newlines def_kw ident lparen param_list rparen block > method_decl

    block
        = lbracket (newlines stmt terminator)* rbracket spacing > block

    stmt
        = assign_stmt
        / if_stmt
        / while_stmt
        / expr

    if_stmt
        = if_kw expr block (else_kw block)? > if_stmt

    while_stmt
        = while_kw expr block > while_stmt

    function_call
        = ident lparen arg_list rparen

    method_call
        = callable_expr (dot function_call)+

    assign_stmt
        = ident bind_op expr > assign_stmt

    expr
        = newlines cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = method_call > method_call
        / callable_expr

    callable_expr
        = function_call > function_call
        / literal
        / constant
        / ident
        / lparen expr rparen

    arg_list
        = empty_list
        / expr (comma expr)* > arg_list

    param_list
        = empty_list
        / ident (comma ident)* > param_list

    empty_list = &rparen > empty_list

    digit = ["0-9"]
    ident_char = ["A-Za-z0-9_"]

    ident = !digit !keyword ident_char+ spacing > ident
    constant = !keyword !digit ["A-Z"]+ ident_char+ spacing > constant

    literal
        = string_lit
        / float_lit
        / int_lit
        / array_lit
        / map_lit

    int_lit = digit+ spacing > int_lit
    float_lit = digit+ dot digit+ spacing > float_lit
    string_lit = (dbl_quot_string_lit / sng_quot_string_lit) spacing > string_lit
    array_lit = lsqbracket expr (comma expr)* rsqbracket > array_lit

    map_entry =  (expr colon expr)
    map_lit = lbracket map_entry (comma map_entry)* rbracket > map_lit

    dbl_quot_string_lit = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_string_lit = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \r\t"]
    spacing = spacing_char* -> ()
    newline = "\n" spacing -> ()
    semicolon = ";" spacing -> ()
    terminator = newline / semicolon -> ()
    newlines = newline* spacing -> ()

    class_kw = "class" spacing
    def_kw = "def" spacing
    else_kw = "else" spacing
    false_kw = "false" spacing
    if_kw = "if" spacing
    nil_kw = "nil" spacing
    true_kw = "true" spacing
    while_kw = "while" spacing

    keyword
        = def_kw
        / if_kw
        / else_kw
        / class_kw
        / true_kw
        / false_kw
        / nil_kw

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" newlines -> ()
    rbracket = newlines "}" -> ()
    lsqbracket = "[" spacing
    rsqbracket = "]" spacing
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    dot = "." spacing
    comma = "," spacing
    colon = ":" spacing

    fn int_lit(raw_text: Vec<char>) -> PNode {
        PNode(IntLit(to_number(raw_text)))
    }

    fn float_lit(mut integer: Vec<char>, fractional: Vec<char>) -> PNode {
        integer.push('.');
        PNode(FltLit(to_float(combine(integer, fractional))))
    }

    fn string_lit(raw_text: Vec<char>) -> PNode {
        PNode(StrLit(to_string(raw_text)))
    }

    fn array_lit(first: PNode, rest: Vec<PNode>) -> PNode {
        PNode(ArrLit(combine_one_with_many(first, rest)))
    }

    fn map_lit(first: (PNode, PNode), rest: Vec<(PNode, PNode)>) -> PNode {
        PNode(MapLit(combine_one_with_many(first, rest)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PNode {
        PNode(Const(to_string(combine(first, rest))))
    }

    fn ident(raw_text: Vec<char>) -> PNode {
        PNode(Ident(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn function_call(func: PNode, args: Vec<PNode>) -> PNode {
        PNode(Message { recv: None, meth: func, args: args })
    }

    fn method_call(recv: PNode, call: Vec<(PNode, Vec<PNode>)>) -> PNode {
        call.into_iter().fold(recv, { |accu, (method, args)|
            PNode(Message { recv: Some(accu), meth: method, args: args })
        })
    }

    fn assign_stmt(var: PNode, expr: PNode) -> PNode {
        PNode(AssignStmt { var: var, expr: expr })
    }

    fn class_decl(class: PNode, methods: Vec<PNode>) -> PNode {
        PNode(ClassDecl { class: class, meths: methods })
    }

    fn method_decl(meth: PNode, params: Vec<PNode>, block: PNode) -> PNode {
        PNode(MethodDecl { meth: meth, params: params, blk: block })
    }

    fn block(stmts: Vec<PNode>) -> PNode {
        PNode(Block(stmts))
    }

    fn program(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn if_stmt(cond: PNode, true_blk: PNode, false_blk: Option<PNode>) -> PNode {
        PNode(IfStmt { cond: cond, true_blk: true_blk, false_blk: false_blk })
    }

    fn while_stmt(cond: PNode, blk: PNode) -> PNode {
        PNode(WhileStmt { cond: cond, blk: blk })
    }

    fn arg_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn param_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn empty_list() -> Vec<PNode> {
        vec![]
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u64 {
        u64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f64 {
        f64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PNode, rest: Vec<(BinOp, PNode)>) -> PNode {
        rest.into_iter().fold(head,
          |accu, (op, expr)| PNode(BinExpr { op: op, left: accu, right: expr }))
    }

    fn fold_right(front: Vec<(PNode, BinOp)>, last: PNode) -> PNode {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| PNode(BinExpr { op: op, left: expr, right: accu }))
    }

    fn combine<T: Clone>(mut left: Vec<T>, right: Vec<T>) -> Vec<T> {
        left.extend(right.into_iter());
        left
    }

    fn combine_one_with_many<T: Clone>(first: T, rest: Vec<T>) -> Vec<T> {
        combine(vec![first], rest)
    }
}

pub struct Parser {
    pub ast: Option<Vec<PNode>>,
}

impl Parser {
    pub fn new() -> Parser {
        Parser { ast: None }
    }

    pub fn parse_file(&mut self, file_path: String) -> Result<Vec<PNode>, String> {
        match File::open(file_path) {
            Ok(file) => {
                let mut reader = BufReader::new(file);
                let mut code = String::new();
                let _ = reader.read_to_string(&mut code);
                self.parse(code)
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }

    pub fn parse(&mut self, code: String) -> Result<Vec<PNode>, String> {
        let state = bailey::parse_program(code.stream());

        match state.into_result() {
            Ok((success, error)) => {
                if success.partial_read() {
                    Err(format!("Partial match: {:?} because: {}", success.data, error))
                } else {
                    self.ast = Some(success.data.clone());
                    Ok(success.data)
                }
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }
}
<commit_msg>Adding newlines everywhere to allow more valid programs to parse.<commit_after>use oak_runtime::stream::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

use ast::PNode;

grammar! bailey {
    use ast::PNode;
    use ast::Node::*;
    use ast::BinOp;
    use ast::BinOp::*;
    use std::str::FromStr;

    program
        = (newlines stmt_or_decl terminator)*

    stmt_or_decl
        = stmt
        / decl

    decl
        = class_decl
        / method_decl

    class_decl
        = class_kw constant class_body > class_decl

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = newlines def_kw ident lparen param_list rparen block > method_decl

    block
        = newlines lbracket (newlines stmt terminator)* rbracket spacing > block

    stmt
        = assign_stmt
        / if_stmt
        / while_stmt
        / expr

    if_stmt
        = if_kw expr block (else_kw block)? > if_stmt

    while_stmt
        = while_kw expr block > while_stmt

    function_call
        = newlines ident lparen arg_list rparen

    method_call
        = callable_expr (dot function_call)+

    assign_stmt
        = ident bind_op expr > assign_stmt

    expr
        = newlines cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = method_call > method_call
        / callable_expr

    callable_expr
        = function_call > function_call
        / literal
        / constant
        / ident
        / lparen expr rparen

    arg_list
        = empty_list
        / expr (comma expr)* > arg_list

    param_list
        = empty_list
        / ident (comma ident)* > param_list

    empty_list = &rparen > empty_list

    digit = ["0-9"]
    ident_char = ["A-Za-z0-9_"]

    ident = !digit !keyword ident_char+ spacing > ident
    constant = !keyword !digit ["A-Z"]+ ident_char+ spacing > constant

    literal
        = string_lit
        / float_lit
        / int_lit
        / array_lit
        / map_lit

    int_lit = digit+ spacing > int_lit
    float_lit = digit+ dot digit+ spacing > float_lit
    string_lit = (dbl_quot_string_lit / sng_quot_string_lit) spacing > string_lit
    array_lit = lsqbracket expr (comma expr)* rsqbracket > array_lit

    map_entry =  (expr colon expr)
    map_lit = lbracket map_entry (comma map_entry)* rbracket > map_lit

    dbl_quot_string_lit = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_string_lit = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \r\t"]
    spacing = spacing_char* -> ()
    newline = "\n" spacing -> ()
    semicolon = ";" spacing -> ()
    terminator = newline / semicolon -> ()
    newlines = newline* spacing -> ()

    class_kw = "class" spacing
    def_kw = "def" spacing
    else_kw = "else" spacing
    false_kw = "false" spacing
    if_kw = "if" spacing
    nil_kw = "nil" spacing
    true_kw = "true" spacing
    while_kw = "while" spacing

    keyword
        = def_kw
        / if_kw
        / else_kw
        / class_kw
        / true_kw
        / false_kw
        / nil_kw

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" newlines -> ()
    rparen = newlines ")" -> ()
    lbracket = "{" newlines -> ()
    rbracket = newlines "}" -> ()
    lsqbracket = "[" newlines
    rsqbracket = newlines "]"
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    dot = "." spacing
    comma = "," spacing
    colon = ":" spacing

    fn int_lit(raw_text: Vec<char>) -> PNode {
        PNode(IntLit(to_number(raw_text)))
    }

    fn float_lit(mut integer: Vec<char>, fractional: Vec<char>) -> PNode {
        integer.push('.');
        PNode(FltLit(to_float(combine(integer, fractional))))
    }

    fn string_lit(raw_text: Vec<char>) -> PNode {
        PNode(StrLit(to_string(raw_text)))
    }

    fn array_lit(first: PNode, rest: Vec<PNode>) -> PNode {
        PNode(ArrLit(combine_one_with_many(first, rest)))
    }

    fn map_lit(first: (PNode, PNode), rest: Vec<(PNode, PNode)>) -> PNode {
        PNode(MapLit(combine_one_with_many(first, rest)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PNode {
        PNode(Const(to_string(combine(first, rest))))
    }

    fn ident(raw_text: Vec<char>) -> PNode {
        PNode(Ident(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn function_call(func: PNode, args: Vec<PNode>) -> PNode {
        PNode(Message { recv: None, meth: func, args: args })
    }

    fn method_call(recv: PNode, call: Vec<(PNode, Vec<PNode>)>) -> PNode {
        call.into_iter().fold(recv, { |accu, (method, args)|
            PNode(Message { recv: Some(accu), meth: method, args: args })
        })
    }

    fn assign_stmt(var: PNode, expr: PNode) -> PNode {
        PNode(AssignStmt { var: var, expr: expr })
    }

    fn class_decl(class: PNode, methods: Vec<PNode>) -> PNode {
        PNode(ClassDecl { class: class, meths: methods })
    }

    fn method_decl(meth: PNode, params: Vec<PNode>, block: PNode) -> PNode {
        PNode(MethodDecl { meth: meth, params: params, blk: block })
    }

    fn block(stmts: Vec<PNode>) -> PNode {
        PNode(Block(stmts))
    }

    fn program(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn if_stmt(cond: PNode, true_blk: PNode, false_blk: Option<PNode>) -> PNode {
        PNode(IfStmt { cond: cond, true_blk: true_blk, false_blk: false_blk })
    }

    fn while_stmt(cond: PNode, blk: PNode) -> PNode {
        PNode(WhileStmt { cond: cond, blk: blk })
    }

    fn arg_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn param_list(first: PNode, mut rest: Vec<PNode>) -> Vec<PNode> {
        combine_one_with_many(first, rest)
    }

    fn empty_list() -> Vec<PNode> {
        vec![]
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u64 {
        u64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f64 {
        f64::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PNode, rest: Vec<(BinOp, PNode)>) -> PNode {
        rest.into_iter().fold(head,
          |accu, (op, expr)| PNode(BinExpr { op: op, left: accu, right: expr }))
    }

    fn fold_right(front: Vec<(PNode, BinOp)>, last: PNode) -> PNode {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| PNode(BinExpr { op: op, left: expr, right: accu }))
    }

    fn combine<T: Clone>(mut left: Vec<T>, right: Vec<T>) -> Vec<T> {
        left.extend(right.into_iter());
        left
    }

    fn combine_one_with_many<T: Clone>(first: T, rest: Vec<T>) -> Vec<T> {
        combine(vec![first], rest)
    }
}

pub struct Parser {
    pub ast: Option<Vec<PNode>>,
}

impl Parser {
    pub fn new() -> Parser {
        Parser { ast: None }
    }

    pub fn parse_file(&mut self, file_path: String) -> Result<Vec<PNode>, String> {
        match File::open(file_path) {
            Ok(file) => {
                let mut reader = BufReader::new(file);
                let mut code = String::new();
                let _ = reader.read_to_string(&mut code);
                self.parse(code)
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }

    pub fn parse(&mut self, code: String) -> Result<Vec<PNode>, String> {
        let state = bailey::parse_program(code.stream());

        match state.into_result() {
            Ok((success, error)) => {
                if success.partial_read() {
                    Err(format!("Partial match: {:?} because: {}", success.data, error))
                } else {
                    self.ast = Some(success.data.clone());
                    Ok(success.data)
                }
            }
            Err(error) => Err(format!("Error: {}", error)),
        }
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use raft::client::{RaftClient, SubscriptionError};
use raft::state_machine::master::ExecError;
use bifrost_hasher::hash_str;
use super::raft::client::SMClient;
use super::DEFAULT_SERVICE_ID;

pub type WatchResult = Result<Result<u64, SubscriptionError>, ExecError>;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Member {
    pub id: u64,
    pub address: String,
    pub online: bool,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Group {
    pub id: u64,
    pub name: String,
    pub members: u64,
}

pub struct MemberClient {
    pub id: u64,
    pub sm_client: Arc<SMClient>
}

impl MemberClient {
    pub fn join_group(&self, group: &String) -> Result<Result<(), ()>, ExecError> {
        self.sm_client.join_group(group, &self.id)
    }
    pub fn leave_group(&self, group: &String) -> Result<Result<(), ()>, ExecError> {
        self.sm_client.leave_group(&hash_str(group), &self.id)
    }
}

pub struct ObserverClient {
    pub sm_client: Arc<SMClient>
}

impl ObserverClient {
    pub fn new(raft_client: &Arc<RaftClient>) -> ObserverClient {
        ObserverClient {
            sm_client: Arc::new(SMClient::new(DEFAULT_SERVICE_ID, &raft_client))
        }
    }
    pub fn new_from_sm(sm_client: &Arc<SMClient>) -> ObserverClient {
        ObserverClient {
            sm_client: sm_client.clone()
        }
    }
    pub fn new_group(&self, name: &String) -> Result<Result<u64, u64>, ExecError> {
        self.sm_client.new_group(name)
    }
    pub fn del_group(&self, name: &String) -> Result<Result<(), ()>, ExecError> {
        self.sm_client.del_group(&hash_str(name))
    }
    pub fn group_leader(&self, group: &String) -> Result<Result<(Option<Member>, u64), ()>, ExecError> {
        self.sm_client.group_leader(&hash_str(group))
    }
    pub fn group_members(&self, group: &String, online_only: bool) -> Result<Result<(Vec<Member>, u64), ()>, ExecError> {
        self.sm_client.group_members(&hash_str(group), &online_only)
    }
    pub fn all_members(&self, online_only: bool) -> Result<Result<(Vec<Member>, u64), ()>, ExecError> {
        self.sm_client.all_members(&online_only)
    }
    pub fn on_group_member_offline<'a, F>(&self, f: F, group: &'a str) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_group_member_offline(f, &hash_str(group))
    }
    pub fn on_any_member_offline<F>(&self, f: F) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_any_member_offline(f)
    }
    pub fn on_group_member_online<'a, F>(&self, f: F, group: &'a str) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_group_member_online(f, &hash_str(group))
    }
    pub fn on_any_member_online<F>(&self, f: F) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_any_member_online(f)
    }
    pub fn on_group_member_joined<'a, F>(&self, f: F, group: &'a str) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_group_member_joined(f, &hash_str(group))
    }
    pub fn on_any_member_joined<F>(&self, f: F) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_any_member_joined(f)
    }
    pub fn on_group_member_left<'a, F>(&self, f: F, group: &'a str) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_group_member_left(f, &hash_str(group))
    }
    pub fn on_any_member_left<F>(&self, f: F) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_any_member_left(f)
    }
    pub fn on_group_leader_changed<F>(&self, f: F, group: &String)
        -> WatchResult
        where F: Fn(Result<(Option<Member>, Option<Member>, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_group_leader_changed(f, &hash_str(group))
    }
}<commit_msg>membership client function interfaces<commit_after>use std::sync::Arc;
use raft::client::{RaftClient, SubscriptionError};
use raft::state_machine::master::ExecError;
use bifrost_hasher::hash_str;
use super::raft::client::SMClient;
use super::DEFAULT_SERVICE_ID;

use futures::prelude::*;

pub type WatchResult = impl Future<Item = Result<u64, SubscriptionError>, Error = ExecError>;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Member {
    pub id: u64,
    pub address: String,
    pub online: bool,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Group {
    pub id: u64,
    pub name: String,
    pub members: u64,
}

pub struct MemberClient {
    pub id: u64,
    pub sm_client: Arc<SMClient>
}

impl MemberClient {
    pub fn join_group(&self, group: &String) -> impl Future<Item = Result<(), ()>, Error = ExecError> {
        self.sm_client.join_group(group, &self.id)
    }
    pub fn leave_group(&self, group: &String) -> impl Future<Item = Result<(), ()>, Error = ExecError> {
        self.sm_client.leave_group(&hash_str(group), &self.id)
    }
}

pub struct ObserverClient {
    pub sm_client: Arc<SMClient>
}

impl ObserverClient {
    pub fn new(raft_client: &Arc<RaftClient>) -> ObserverClient {
        ObserverClient {
            sm_client: Arc::new(SMClient::new(DEFAULT_SERVICE_ID, &raft_client))
        }
    }
    pub fn new_from_sm(sm_client: &Arc<SMClient>) -> ObserverClient {
        ObserverClient {
            sm_client: sm_client.clone()
        }
    }
    pub fn new_group(&self, name: &String) -> impl Future<Item = Result<u64, u64>, Error = ExecError> {
        self.sm_client.new_group(name)
    }
    pub fn del_group(&self, name: &String) -> impl Future<Item = Result<(), ()>, Error = ExecError> {
        self.sm_client.del_group(&hash_str(name))
    }
    pub fn group_leader(&self, group: &String) -> impl Future<Item = Result<(Option<Member>, u64), ()>, Error = ExecError> {
        self.sm_client.group_leader(&hash_str(group))
    }
    pub fn group_members(&self, group: &String, online_only: bool) -> impl Future<Item = Result<(Vec<Member>, u64), ()>, Error = ExecError> {
        self.sm_client.group_members(&hash_str(group), &online_only)
    }
    pub fn all_members(&self, online_only: bool) -> impl Future<Item = Result<(Vec<Member>, u64), ()>, Error = ExecError> {
        self.sm_client.all_members(&online_only)
    }
    pub fn on_group_member_offline<'a, F>(&self, f: F, group: &'a str) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_group_member_offline(f, &hash_str(group))
    }
    pub fn on_any_member_offline<F>(&self, f: F) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_any_member_offline(f)
    }
    pub fn on_group_member_online<'a, F>(&self, f: F, group: &'a str) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_group_member_online(f, &hash_str(group))
    }
    pub fn on_any_member_online<F>(&self, f: F) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_any_member_online(f)
    }
    pub fn on_group_member_joined<'a, F>(&self, f: F, group: &'a str) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_group_member_joined(f, &hash_str(group))
    }
    pub fn on_any_member_joined<F>(&self, f: F) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_any_member_joined(f)
    }
    pub fn on_group_member_left<'a, F>(&self, f: F, group: &'a str) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_group_member_left(f, &hash_str(group))
    }
    pub fn on_any_member_left<F>(&self, f: F) -> WatchResult
        where F: Fn(Result<(Member, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_any_member_left(f)
    }
    pub fn on_group_leader_changed<F>(&self, f: F, group: &String)
        -> WatchResult
        where F: Fn(Result<(Option<Member>, Option<Member>, u64), ()>)  + 'static + Send + Sync {
        self.sm_client.on_group_leader_changed(f, &hash_str(group))
    }
}<|endoftext|>