<commit_before>//! Aperture Macros.

use ::{GerberCode, GerberResult};

#[derive(Debug)]
pub struct ApertureMacro {
    pub name: String,
}

#[derive(Debug)]
pub enum Primitive {
    Comment(String),
    Circle(CirclePrimitive),
}

impl GerberCode for Primitive {
    fn to_code(&self) -> GerberResult<String> {
        let code = match *self {
            Primitive::Comment(ref s) => s.clone(),
            Primitive::Circle(ref cp) => try!(cp.to_code()),
        };
        Ok(code)
    }
}

#[derive(Debug)]
pub struct CirclePrimitive {
    /// Exposure off/on
    pub exposure: bool,

    /// Diameter, a decimal >= 0
    pub diameter: f64,

    /// X and Y coordinates of center position, a decimal
    pub center: (f64, f64),

    /// Rotation angle.
    ///
    /// The rotation angle is specified by a decimal, in degrees. The primitive
    /// is rotated around the origin of the macro definition, i.e. the (0, 0)
    /// point of macro coordinates.
    ///
    /// The rotation modifier is optional. The default is no rotation. (We
    /// recommend always to set the angle explicitly.
    pub angle: Option<f64>,
}

impl GerberCode for CirclePrimitive {
    fn to_code(&self) -> GerberResult<String> {
        let mut code = "1,".to_string();
        code.push_str(&try!(self.exposure.to_code()));
        code.push_str(&format!(",{},{},{}", self.diameter, self.center.0, self.center.1));
        if let Some(a) = self.angle {
            code.push_str(&format!(",{}", a));
        }
        Ok(code)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use ::GerberCode;

    #[test]
    fn test_circle_primitive_codegen() {
        let with_angle = CirclePrimitive {
            exposure: true,
            diameter: 1.5,
            center: (0., 0.),
            angle: Some(0.),
        };
        assert_eq!(with_angle.to_code().unwrap(), "1,1,1.5,0,0,0".to_string());
        let no_angle = CirclePrimitive {
            exposure: false,
            diameter: 99.9,
            center: (1.1, 2.2),
            angle: None,
        };
        assert_eq!(no_angle.to_code().unwrap(), "1,0,99.9,1.1,2.2".to_string());
    }
}
<commit_msg>Add VectorLinePrimitive<commit_after>//! Aperture Macros.

use ::{GerberCode, GerberResult};

#[derive(Debug)]
pub struct ApertureMacro {
    pub name: String,
}

#[derive(Debug)]
pub enum Primitive {
    Comment(String),
    Circle(CirclePrimitive),
    VectorLine(VectorLinePrimitive),
}

impl GerberCode for Primitive {
    fn to_code(&self) -> GerberResult<String> {
        let code = match *self {
            Primitive::Comment(ref s) => s.clone(),
            Primitive::Circle(ref cp) => try!(cp.to_code()),
            Primitive::VectorLine(ref cp) => try!(cp.to_code()),
        };
        Ok(code)
    }
}

#[derive(Debug)]
pub struct CirclePrimitive {
    /// Exposure off/on
    pub exposure: bool,

    /// Diameter, a decimal >= 0
    pub diameter: f64,

    /// X and Y coordinates of center position, a decimal
    pub center: (f64, f64),

    /// Rotation angle.
    ///
    /// The rotation angle is specified by a decimal, in degrees. The primitive
    /// is rotated around the origin of the macro definition, i.e. the (0, 0)
    /// point of macro coordinates.
    ///
    /// The rotation modifier is optional. The default is no rotation. (We
    /// recommend always to set the angle explicitly.
    pub angle: Option<f64>,
}

impl GerberCode for CirclePrimitive {
    fn to_code(&self) -> GerberResult<String> {
        let mut code = "1,".to_string();
        code.push_str(&try!(self.exposure.to_code()));
        code.push_str(&format!(",{},{},{}", self.diameter, self.center.0, self.center.1));
        if let Some(a) = self.angle {
            code.push_str(&format!(",{}", a));
        }
        Ok(code)
    }
}

#[derive(Debug)]
pub struct VectorLinePrimitive {
    /// Exposure off/on
    pub exposure: bool,

    /// Line width, a decimal >= 0
    pub width: f64,

    /// Coordinates of start point, a decimal
    pub start: (f64, f64),

    /// Coordinates of end point, a decimal
    pub end: (f64, f64),

    /// Rotation angle of the vector line primitive
    ///
    /// The rotation angle is specified by a decimal, in degrees. The primitive
    /// is rotated around the origin of the macro definition, i.e. the (0, 0)
    /// point of macro coordinates.
    pub angle: f64,
}

impl GerberCode for VectorLinePrimitive {
    fn to_code(&self) -> GerberResult<String> {
        let code = format!(
            "20,{},{},{},{},{},{},{}",
            try!(self.exposure.to_code()),
            self.width,
            self.start.0, self.start.1, self.end.0, self.end.1,
            self.angle
        );
        Ok(code)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use ::GerberCode;

    #[test]
    fn test_circle_primitive_codegen() {
        let with_angle = CirclePrimitive {
            exposure: true,
            diameter: 1.5,
            center: (0., 0.),
            angle: Some(0.),
        };
        assert_eq!(with_angle.to_code().unwrap(), "1,1,1.5,0,0,0".to_string());
        let no_angle = CirclePrimitive {
            exposure: false,
            diameter: 99.9,
            center: (1.1, 2.2),
            angle: None,
        };
        assert_eq!(no_angle.to_code().unwrap(), "1,0,99.9,1.1,2.2".to_string());
    }

    #[test]
    fn test_vector_line_primitive_codegen() {
        let line = VectorLinePrimitive {
            exposure: true,
            width: 0.9,
            start: (0., 0.45),
            end: (12., 0.45),
            angle: 0.,
        };
        assert_eq!(line.to_code().unwrap(), "20,1,0.9,0,0.45,12,0.45,0".to_string());
    }
}
<|endoftext|>


<commit_before>/// A 2D Matrix type composed of `f64` elements.
///
/// The Matrix type supports simple arithmetic operations from the start and
/// provides convenient methods for accessing the elements of the matrix.
///
/// # Examples
/// ```
/// // Create a new 2x2 matrix with all values 0.0
/// let m1 = Matrix::new(2, 2, 0.0);
///
/// // Creates a 2x2 matrix from the above vector in row major order
/// let elems = [1.0, 2.0, 3.0, 4.0];
/// let m2 = Matrix::from_elems(2, 2, elems.as_slice());
///
/// let res = m1 + m2; // add two matrices
/// res = m1 - m2; // subtract 2 matrices
/// res = m1 * m2; // matrix product of 2 matrices
/// res = m2 * 5.0; // scalar product of a matrix
/// ```

pub struct Matrix {
  rows: uint,
  cols: uint,
  data: Vec<f64>
}

impl Index<uint, [f64]> for Matrix {
  #[inline]
  fn index<'a>(&'a self, index: &uint) -> &'a [f64] {
    self.data.as_slice().slice(self.rows * *index, self.rows * *index + self.cols)
  }
}

impl Clone for Matrix {
  fn clone(&self) -> Matrix {
    Matrix {
      rows: self.num_rows(),
      cols: self.num_cols(),
      data: self.data.clone()
    }
  }

  fn clone_from(&mut self, source: &Matrix) {
    self.rows = source.num_rows();
    self.cols = source.num_cols();
    self.data = source.data.clone();
  }
}

impl Add<Matrix, Matrix> for Matrix {
  fn add(self, rhs: Matrix) -> Matrix {
    if self.num_rows() == rhs.num_rows() && self.num_cols() == rhs.num_cols() {
      let mut new_mat = Matrix::new(self.num_rows(), self.num_cols(), 0.0);
      for i in range(0, self.data.len()) {
        new_mat.data[i] = self.data[i] + rhs.data[i];
      }
      new_mat
    } else {
      panic!("Matrices are not conformable for addition.");
    }
  }
}

impl Sub<Matrix, Matrix> for Matrix {
  fn sub(self, rhs: Matrix) -> Matrix {
    if self.num_rows() == rhs.num_rows() && self.num_cols() == rhs.num_cols() {
      let mut new_mat = Matrix::new(self.num_rows(), self.num_cols(), 0.0);
      for i in range(0, self.data.len()) {
        new_mat.data[i] = self.data[i] - rhs.data[i];
      }
      new_mat
    } else {
      panic!("Matrices are not conformable for subtraction.");
    }
  }
}

impl Mul<Matrix, Matrix> for Matrix {
  fn mul(self, rhs: Matrix) -> Matrix {
    if self.num_cols() == rhs.num_rows() {
      let mut new_mat = Matrix::new(self.num_rows(), rhs.num_cols(), 0.0);
      for i in range(0, self.num_rows()) {
        for j in range(0, rhs.num_cols()) {
          let mut sum: f64 = 0.0;
          for k in range(0, self.num_cols()) {
            sum += self.get(i, k) * rhs.get(k, j);
          }
          new_mat.set(i, j, sum);
        }
      }
      new_mat
    } else {
      panic!("Matrices are not conformable for multiplication.")
    }
  }
}

impl Neg<Matrix> for Matrix {
  fn neg(self) -> Matrix {
    let mut m = self.clone();
    for i in range(0, self.data.len()) {
      m.data[i] = -self.data[i];
    }
    m
  }
}

impl Mul<f64, Matrix> for Matrix {
  fn mul(self, rhs: f64) -> Matrix {
    let mut m = self.clone();
    for i in range(0, self.data.len()) {
      m.data[i] = rhs * self.data[i];
    }
    m
  }
}

impl PartialEq for Matrix {
  fn eq(&self, other: &Matrix) -> bool {
    if self.num_rows() != other.num_rows() || self.num_cols() != other.num_cols() {
      return false;
    }
    for i in range(0, self.data.len()) {
      if self.data[i] != other.data[i] {
        return false;
      }
    }
    true
  }
}

impl Eq for Matrix {}

impl Matrix {
  /// Returns the number of rows in the matrix.
  #[inline]
  pub fn num_rows(&self) -> uint{
    self.rows
  }

  /// Returns the number of columns in the matrix.
  #[inline]
  pub fn num_cols(&self) -> uint {
    self.cols
  }

  /// Returns the element at `i`th row and `j`th column of the matrix.
  /// The row, column indexing is 0-based.
  #[inline]
  pub fn get(&self, i: uint, j: uint) -> f64 {
    if i < self.num_rows() && j < self.num_cols() {
      self.data[i * self.num_cols() + j]
    } else {
      panic!(format!("Matrix index {} out of bounds.", (i, j)))
    }
  }

  /// Sets the element at `i`th row and `j`th column of the matrix as `num`.
  /// The row, column indexing is 0-based.
  #[inline]
  pub fn set(&mut self, i: uint, j: uint, num: f64) {
    if i < self.num_rows() && j < self.num_cols() {
      self.data.as_mut_slice()[i * self.num_cols() + j] = num
    } else {
      panic!(format!("Matrix index {} out of bounds.", (i, j)))
    }
  }

  /// Creates a new `Matrix` with dimensions as `rows x cols` with all values
  /// instantiated to `default`.
  pub fn new(rows: uint, cols: uint, default: f64) -> Matrix {
    Matrix {
      rows: rows,
      cols: cols,
      data: Vec::from_elem(rows * cols, default)
    }
  }

  /// Resizes the dimensions of the matrix with the new dimensions as
  /// `newrows x newcols`.
  pub fn reshape(&mut self, newrows: uint, newcols: uint) {
    if self.rows * self.cols == newrows * newcols {
      self.rows = newrows;
      self.cols = newcols;
    } else {
      panic!("Total number of elements in matrix should be same.")
    }
  }

  /// Returns the matrix as a cloned vector in row major order.
  pub fn get_vec(&self) -> Vec<f64> {
    self.data.clone()
  }

  /// Transposes the matrix.
  pub fn transpose(&mut self) {
    let mut v = self.data.clone();
    for i in range(0, self.num_rows()) {
      for j in range(0, self.num_cols()) {
        v[j * self.num_cols() + i] = self.get(i, j);
      }
    }
    self.data = v;
  }

  /// Trace of the matrix.
  pub fn trace(&self) -> f64 {
    if self.num_rows() == self.num_cols() {
      let mut sum: f64 = 0.0;
      for i in range(0, self.num_rows()) {
        sum += self.get(i, i);
      }
      return sum;
    }
    panic!("The matrix should be a square matrix.")
  }
}

/// Creates a `Matrix` with dimensions `rows x cols` from the elements of the
/// slice `elems`.
pub fn from_elems(rows: uint, cols: uint, elems: &[f64]) -> Matrix {
  let mut m = Matrix {
    rows: rows,
    cols: cols,
    data: Vec::new()
  };
  m.data.push_all(elems);
  m
}

/// Creates an identity matrix of dimension `n x n`.
pub fn identity(n: uint) -> Matrix {
  let mut m = Matrix {
    rows: n,
    cols: n,
    data: Vec::from_elem(n * n, 0.0)
  };
  for i in range(0, n) {
    m.set(i, i, 1.0);
  }
  m
}
<commit_msg>rustup v1.0-alpha<commit_after>/// A 2D Matrix type composed of `f64` elements.
///
/// The Matrix type supports simple arithmetic operations from the start and
/// provides convenient methods for accessing the elements of the matrix.
///
/// # Examples
/// ```
/// use numrs::matrix;
/// use numrs::matrix::Matrix;
///
/// // Create a new 2x2 matrix with all values 0.0
/// let m1 = Matrix::new(2, 2, 0.0);
///
/// // Creates a 2x2 matrix from the above vector in row major order
/// let elems = [1.0, 2.0, 3.0, 4.0];
/// let m2 = matrix::from_elems(2, 2, elems.as_slice());
///
/// let mut res = m1.clone() + m2.clone(); // add two matrices
/// res = m1.clone() - m2.clone(); // subtract 2 matrices
/// res = m1.clone() * m2.clone(); // matrix product of 2 matrices
/// res = m2.clone() * 5.0; // scalar product of a matrix
/// ```

use std::ops::{Index, Add, Sub, Mul, Neg};

pub struct Matrix {
  rows: usize,
  cols: usize,
  data: Vec<f64>
}

impl Index<usize> for Matrix {
  type Output = [f64];

  #[inline]
  fn index<'a>(&'a self, index: &usize) -> &'a [f64] {
    self.data.as_slice().slice(self.rows * *index, self.rows * *index + self.cols)
  }
}

impl Clone for Matrix {
  fn clone(&self) -> Matrix {
    Matrix {
      rows: self.num_rows(),
      cols: self.num_cols(),
      data: self.data.clone()
    }
  }

  fn clone_from(&mut self, source: &Matrix) {
    self.rows = source.num_rows();
    self.cols = source.num_cols();
    self.data = source.data.clone();
  }
}

impl Add<Matrix> for Matrix {
  type Output = Matrix;

  fn add(self, rhs: Matrix) -> Matrix {
    if self.num_rows() == rhs.num_rows() && self.num_cols() == rhs.num_cols() {
      let mut new_mat = Matrix::new(self.num_rows(), self.num_cols(), 0.0);
      for i in range(0, self.data.len()) {
        new_mat.data[i] = self.data[i] + rhs.data[i];
      }
      new_mat
    } else {
      panic!("Matrices are not conformable for addition.");
    }
  }
}

impl Sub<Matrix> for Matrix {
  type Output = Matrix;

  fn sub(self, rhs: Matrix) -> Matrix {
    if self.num_rows() == rhs.num_rows() && self.num_cols() == rhs.num_cols() {
      let mut new_mat = Matrix::new(self.num_rows(), self.num_cols(), 0.0);
      for i in range(0, self.data.len()) {
        new_mat.data[i] = self.data[i] - rhs.data[i];
      }
      new_mat
    } else {
      panic!("Matrices are not conformable for subtraction.");
    }
  }
}

impl Mul<Matrix> for Matrix {
  type Output = Matrix;

  fn mul(self, rhs: Matrix) -> Matrix {
    if self.num_cols() == rhs.num_rows() {
      let mut new_mat = Matrix::new(self.num_rows(), rhs.num_cols(), 0.0);
      for i in range(0, self.num_rows()) {
        for j in range(0, rhs.num_cols()) {
          let mut sum: f64 = 0.0;
          for k in range(0, self.num_cols()) {
            sum += self.get(i, k) * rhs.get(k, j);
          }
          new_mat.set(i, j, sum);
        }
      }
      new_mat
    } else {
      panic!("Matrices are not conformable for multiplication.")
    }
  }
}

impl Neg for Matrix {
  type Output = Matrix;

  fn neg(self) -> Matrix {
    let mut m = self.clone();
    for i in range(0, self.data.len()) {
      m.data[i] = -self.data[i];
    }
    m
  }
}

impl Mul<f64> for Matrix {
  type Output = Matrix;

  fn mul(self, rhs: f64) -> Matrix {
    let mut m = self.clone();
    for i in range(0, self.data.len()) {
      m.data[i] = rhs * self.data[i];
    }
    m
  }
}

impl PartialEq for Matrix {
  fn eq(&self, other: &Matrix) -> bool {
    if self.num_rows() != other.num_rows() || self.num_cols() != other.num_cols() {
      return false;
    }
    for i in range(0, self.data.len()) {
      if self.data[i] != other.data[i] {
        return false;
      }
    }
    true
  }
}

impl Eq for Matrix {}

impl Matrix {
  /// Returns the number of rows in the matrix.
  #[inline]
  pub fn num_rows(&self) -> usize{
    self.rows
  }

  /// Returns the number of columns in the matrix.
  #[inline]
  pub fn num_cols(&self) -> usize {
    self.cols
  }

  /// Returns the element at `i`th row and `j`th column of the matrix.
  /// The row, column indexing is 0-based.
  #[inline]
  pub fn get(&self, i: usize, j: usize) -> f64 {
    if i < self.num_rows() && j < self.num_cols() {
      self.data[i * self.num_cols() + j]
    } else {
      panic!(format!("Matrix index ({}, {}) out of bounds.", i, j))
    }
  }

  /// Sets the element at `i`th row and `j`th column of the matrix as `num`.
  /// The row, column indexing is 0-based.
  #[inline]
  pub fn set(&mut self, i: usize, j: usize, num: f64) {
    if i < self.num_rows() && j < self.num_cols() {
      self.data.as_mut_slice()[i * self.num_cols() + j] = num
    } else {
      panic!(format!("Matrix index ({}, {}) out of bounds.", i, j))
    }
  }

  /// Creates a new `Matrix` with dimensions as `rows x cols` with all values
  /// instantiated to `default`.
  pub fn new(rows: usize, cols: usize, default: f64) -> Matrix {
    let mut d: Vec<f64> = Vec::with_capacity(rows * cols);
    for i in range(0, rows * cols) {
      d.push(default);
    }
    Matrix {
      rows: rows,
      cols: cols,
      data: d
    }
  }

  /// Resizes the dimensions of the matrix with the new dimensions as
  /// `newrows x newcols`.
  pub fn reshape(&mut self, newrows: usize, newcols: usize) {
    if self.rows * self.cols == newrows * newcols {
      self.rows = newrows;
      self.cols = newcols;
    } else {
      panic!("Total number of elements in matrix should be same.")
    }
  }

  /// Returns the matrix as a cloned vector in row major order.
  pub fn get_vec(&self) -> Vec<f64> {
    self.data.clone()
  }

  /// Transposes the matrix.
  pub fn transpose(&mut self) {
    let mut v = self.data.clone();
    for i in range(0, self.num_rows()) {
      for j in range(0, self.num_cols()) {
        v[j * self.num_cols() + i] = self.get(i, j);
      }
    }
    self.data = v;
  }

  /// Trace of the matrix.
  pub fn trace(&self) -> f64 {
    if self.num_rows() == self.num_cols() {
      let mut sum: f64 = 0.0;
      for i in range(0, self.num_rows()) {
        sum += self.get(i, i);
      }
      return sum;
    }
    panic!("The matrix should be a square matrix.")
  }
}

/// Creates a `Matrix` with dimensions `rows x cols` from the elements of the
/// slice `elems`.
pub fn from_elems(rows: usize, cols: usize, elems: &[f64]) -> Matrix {
  let mut m = Matrix {
    rows: rows,
    cols: cols,
    data: Vec::new()
  };
  m.data.push_all(elems);
  m
}

/// Creates an identity matrix of dimension `n x n`.
pub fn identity(n: usize) -> Matrix {
  let mut m = Matrix::new(n, n, 0.0);
  for i in range(0, n) {
    m.set(i, i, 1.0);
  }
  m
}
<|endoftext|>


<commit_before>//! VM memory representation

use bigint::{U256, M256};

use super::errors::MemoryError;

/// Represent a memory in EVM. Read should always succeed. Write can
/// fall.
pub trait Memory {
    /// Check whether write on this index would result in an error. If
    /// this function returns Ok, then both `write` and `write_raw` on
    /// this index should succeed.
    fn check_write(&self, index: U256) -> Result<(), MemoryError>;
    /// Check whether write on the given index range would result in
    /// an error. If this function returns Ok, then both `write` and
    /// `write_raw` on the given index range should succeed.
    fn check_write_range(&self, start: U256, len: U256) -> Result<(), MemoryError>;

    /// Write value into the index.
    fn write(&mut self, index: U256, value: M256) -> Result<(), MemoryError>;
    /// Write only one byte value into the index.
    fn write_raw(&mut self, index: U256, value: u8) -> Result<(), MemoryError>;
    /// Read value from the index.
    fn read(&self, index: U256) -> M256;
    /// Read only one byte value from the index.
    fn read_raw(&self, index: U256) -> u8;
}

/// A sequencial memory. It uses Rust's `Vec` for internal
/// representation.
pub struct SeqMemory {
    memory: Vec<u8>,
}

impl Default for SeqMemory {
    fn default() -> SeqMemory {
        SeqMemory {
            memory: Vec::new(),
        }
    }
}

impl Memory for SeqMemory {
    fn check_write(&self, index: U256) -> Result<(), MemoryError> {
        let end = index + 32.into();
        if end > U256::from(usize::max_value()) {
            Err(MemoryError::IndexNotSupported)
        } else {
            Ok(())
        }
    }

    fn check_write_range(&self, start: U256, len: U256) -> Result<(), MemoryError> {
        if len == U256::zero() {
            return Ok(());
        }

        if M256::from(start) + M256::from(len) < M256::from(start) {
            Err(MemoryError::IndexNotSupported)
        } else {
            self.check_write(start + len - U256::from(1u64))
        }
    }

    fn write(&mut self, index: U256, value: M256) -> Result<(), MemoryError> {
        let end = M256::from(index) + 32.into();
        if end > M256::from(usize::max_value()) {
            return Err(MemoryError::IndexNotSupported);
        }

        for i in 0..32 {
            self.write_raw(index + i.into(), value.index(i)).unwrap();
        }
        Ok(())
    }

    fn write_raw(&mut self, index: U256, value: u8) -> Result<(), MemoryError> {
        if index > U256::from(usize::max_value()) {
            return Err(MemoryError::IndexNotSupported);
        }

        let index: usize = index.as_usize();

        if self.memory.len() <= index {
            self.memory.resize(index + 1, 0u8);
        }

        self.memory[index] = value;
        Ok(())
    }

    fn read(&self, index: U256) -> M256 {
        let mut a: [u8; 32] = [0u8; 32];

        for i in 0..32 {
            a[i] = self.read_raw(index + i.into());
        }
        a.as_ref().into()
    }

    fn read_raw(&self, index: U256) -> u8 {
        if index > U256::from(usize::max_value()) {
            return 0u8;
        }

        let index: usize = index.as_usize();

        if self.memory.len() <= index {
            return 0u8;
        }

        self.memory[index]
    }
}
<commit_msg>SeqMemory::len and raw_len<commit_after>//! VM memory representation

use bigint::{U256, M256};

use super::errors::MemoryError;

/// Represent a memory in EVM. Read should always succeed. Write can
/// fall.
pub trait Memory {
    /// Check whether write on this index would result in an error. If
    /// this function returns Ok, then both `write` and `write_raw` on
    /// this index should succeed.
    fn check_write(&self, index: U256) -> Result<(), MemoryError>;
    /// Check whether write on the given index range would result in
    /// an error. If this function returns Ok, then both `write` and
    /// `write_raw` on the given index range should succeed.
    fn check_write_range(&self, start: U256, len: U256) -> Result<(), MemoryError>;

    /// Write value into the index.
    fn write(&mut self, index: U256, value: M256) -> Result<(), MemoryError>;
    /// Write only one byte value into the index.
    fn write_raw(&mut self, index: U256, value: u8) -> Result<(), MemoryError>;
    /// Read value from the index.
    fn read(&self, index: U256) -> M256;
    /// Read only one byte value from the index.
    fn read_raw(&self, index: U256) -> u8;
}

/// A sequencial memory. It uses Rust's `Vec` for internal
/// representation.
pub struct SeqMemory {
    memory: Vec<u8>,
}

impl Default for SeqMemory {
    fn default() -> SeqMemory {
        SeqMemory {
            memory: Vec::new(),
        }
    }
}

impl SeqMemory {
    pub fn len(&self) -> usize {
        let len = self.memory.len();
        if len % 32 == 0 {
            len / 32
        } else {
            len / 32 + 1
        }
    }

    pub fn raw_len(&self) -> usize {
        self.memory.len()
    }
}

impl Memory for SeqMemory {
    fn check_write(&self, index: U256) -> Result<(), MemoryError> {
        let end = index + 32.into();
        if end > U256::from(usize::max_value()) {
            Err(MemoryError::IndexNotSupported)
        } else {
            Ok(())
        }
    }

    fn check_write_range(&self, start: U256, len: U256) -> Result<(), MemoryError> {
        if len == U256::zero() {
            return Ok(());
        }

        if M256::from(start) + M256::from(len) < M256::from(start) {
            Err(MemoryError::IndexNotSupported)
        } else {
            self.check_write(start + len - U256::from(1u64))
        }
    }

    fn write(&mut self, index: U256, value: M256) -> Result<(), MemoryError> {
        let end = M256::from(index) + 32.into();
        if end > M256::from(usize::max_value()) {
            return Err(MemoryError::IndexNotSupported);
        }

        for i in 0..32 {
            self.write_raw(index + i.into(), value.index(i)).unwrap();
        }
        Ok(())
    }

    fn write_raw(&mut self, index: U256, value: u8) -> Result<(), MemoryError> {
        if index > U256::from(usize::max_value()) {
            return Err(MemoryError::IndexNotSupported);
        }

        let index: usize = index.as_usize();

        if self.memory.len() <= index {
            self.memory.resize(index + 1, 0u8);
        }

        self.memory[index] = value;
        Ok(())
    }

    fn read(&self, index: U256) -> M256 {
        let mut a: [u8; 32] = [0u8; 32];

        for i in 0..32 {
            a[i] = self.read_raw(index + i.into());
        }
        a.as_ref().into()
    }

    fn read_raw(&self, index: U256) -> u8 {
        if index > U256::from(usize::max_value()) {
            return 0u8;
        }

        let index: usize = index.as_usize();

        if self.memory.len() <= index {
            return 0u8;
        }

        self.memory[index]
    }
}
<|endoftext|>


<commit_before>pub mod defs;
pub mod barrier;
pub mod memory;
<commit_msg>x86_common: Add definition of global start_info<commit_after>use ::xen::StartInfo;

pub mod defs;
pub mod barrier;
pub mod memory;

extern {
    // Start info is not present on all architecture, this is why this
    // was made a global variable only for x86_*
    pub static start_info: *const StartInfo;
}
<|endoftext|>


<commit_before>//#![allow(unused)]

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Condvar, Mutex, Arc};
use std::vec::Vec;
use std::collections::HashMap;
use std::cell::UnsafeCell;
use std::hash::{Hash, Hasher};
use std::mem::{align_of, size_of_val, transmute};
use std::slice::bytes::copy_memory;

use ::Result;

pub struct GlobalState { version : AtomicUsize }

/// Baseline implementation of GlobalState, currently do not hqve the aid of the compiler, so this
/// may have major issues.
/// TODO: make a proper implementation of the GlobalState trait
impl GlobalState {
    fn newLocal<'l, 'g>(&'g self) -> LocalState<'l, 'g> {
        LocalState {
            reads: Vec::new(),
            writes: HashMap::new(),
            global: self,
            snapshot: self.version.load(Ordering::SeqCst),
        }
    }

    pub fn retry<A, F>(&self, l: &mut LocalState, mut func: F) -> A
    where F: FnMut(&mut LocalState) -> Result<A> {
        let bx = Arc::new((Mutex::new(false), Condvar::new()));
        for &(addr, size) in &l.reads {
            let mut waiters = addr.addr.waiters.lock().unwrap();
            // this is actually unsafe...
            // maybe protect waiters with a lock
            waiters.push(bx.clone());
            //addr.waiters().push((&mtx, &cv));
        }
        // currently wont compile because bx is moved
        let (ref mtx, ref cv) = *bx;
        let mut done = mtx.lock().unwrap();
        while !*done {
            done = cv.wait(done).unwrap();
        }
        self.run(func)
    }

    pub fn run<A, F>(&self, mut func : F) -> A
    where F: FnMut(&mut LocalState) -> Result<A> {
        let mut local = self.newLocal();
        match func(&mut local).spec_move() {
            Ok(r) => r,
            _ => self.run(func)
        }
    }

    pub fn or_else<A, F, G>(&self, mut func1 : F, func2 : G) -> A
        where F: FnMut(&mut LocalState) -> Result<A>,
              G: FnMut(&mut LocalState) -> Result<A> {
            let mut local1 = self.newLocal();
            match func1(&mut local1).spec_move() {
                Ok(r) => r,
                //TODO: this may not work, compiler may not know that
                //local1, which borrows self, has relinquised ownership
                _ => self.run(func2)
            }
    }
}

pub struct LocalState<'v, 'g : 'v> {
    /// the norec paper has the reads stored as a list of <address, value> pairs. For us it
    /// would probably be better to have versioned TVars. That way we always have a fast
    /// comparison operation and avoid doing extra dynamic dispatch when validating reads.
    reads : Vec<(TVarAddr<'v, 'g>, usize)>,

    /// for writes we will probably have to cast unsafely to get this to work. TVars just hold
    /// arbitrary types and we only have one table.  XXX: gross
    writes : HashMap<TVarAddr<'v, 'g>, Box<[u8]>>,

    /// STM environment we are using
    /// TODO: how are we getting away with this not being a mutable reference?
    global : &'g GlobalState,

    /// last version at which our view of the global state was valid
    snapshot : usize
}

impl<'v, 'g : 'v> LocalState<'v, 'g> {

    /// Validate the current local state against the state of the world,
    /// Aborts if a TVar in our readset has been written, otherwise
    /// returns the version number to with we are consistent
    pub fn validate(&self) -> Result<usize> {
        loop {
            let time = self.global.version.load(Ordering::SeqCst);
            if (time & 1) == 0 {
                continue;
            }
            for &(addr, version) in &self.reads {
                if addr.version().load(Ordering::SeqCst) != version {
                    return Result::abort();
                }
            }
            return Result::ret(time);
        }
    }

    /// Acquire reference to value in TVar within the transaction
    pub fn read<'l, A>(&'l mut self, tvar : &'v TVar<'g, A>) -> Result<&'l A>
        where 'v : 'l
    {
        let addr: TVarAddr<'v, 'g> = unsafe { tvar.to_addr() } ;

        // Should be &&'l ?
        if let Some(v) = self.writes.get(&addr) {
            let r : && [u8] = &&**v;
            assert_eq!(r.len(), ::std::mem::size_of::<A>());
            let r2 : && A = unsafe { transmute(r) };
            return Result::ret(r2)
        }

        if self.snapshot == self.global.version.load(Ordering::SeqCst) {
            self.reads.push((addr, tvar.version.load(Ordering::SeqCst)));
            Result::ret(unsafe {tvar.get_val()})
        } else {
            self.validate().bind( | v | {
                assert!(self.snapshot <= v);
                self.snapshot = v;
                self.reads.push((addr, tvar.version.load(Ordering::SeqCst)));
                Result::ret(unsafe {tvar.get_val()})
            })
        }
    }

    /// Add the TVar and value to our writeset, these are thread-local until the
    /// transaction commits
    pub fn write<A : Copy>(&mut self, tvar : &'v mut TVar<'g, A>, val : A) -> Result<()> {
        let b : Box<[A]> = Box::new([val]);
        unsafe {
            self.writes.insert(tvar.to_addr(), transmute(b));
        }
        Result::ret(())
    }

    /// if (read−only transaction)
    ///     return
    /// while (!CAS(&global lock, snapshot, snapshot + 1))
    ///     snapshot = Validate()
    /// for each (addr, val) in writes
    ///     ∗addr = val
    /// global lock = snapshot + 2 // one more than CAS above
    pub fn commit(&mut self) -> Result<()> {
        fn commit_loop(l : &mut LocalState) -> Result<()> {
            if l.global
                .version
                .compare_and_swap(l.snapshot, l.snapshot + 1, Ordering::SeqCst) == l.snapshot {
                Result::ret(())
            } else {
                l.validate().bind(|v| {
                    l.snapshot = v;
                    commit_loop(l)
                })
            }
        }
        if self.writes.is_empty() {
            Result::ret(())
        } else {
            commit_loop(self).bind(| _ | {
                for (mut addr, value) in &self.writes {
                    let dst = unsafe { addr.aligned_mem() };
                    debug_assert_eq!(value.len(), dst.len());
                    copy_memory(value, dst);
                    addr.addr.version.fetch_add(1, Ordering::SeqCst);
                    //TODO: DCLP if this is too slow in the common case that waiters is empty
                    let mut waiters = addr.addr.waiters.lock().unwrap();
                    for bx in &*waiters {
                        let (ref mtx, ref cv) = **bx;
                        let mut done = mtx.lock().unwrap();
                        *done = true;
                        cv.notify_all();
                    }
                    // this is safe because we hold the sequence lock
                    waiters.clear();
                    //addr.waiters().clear();
                    //TODO: set waiters to empty
                }
                self.global
                    .version
                    .compare_and_swap(self.snapshot + 1, self.snapshot + 2, Ordering::SeqCst);
                Result::ret(())
            })
        }
    }
}

/// Haskell-style container of mutable state within a transaction
/// TODO: impl TVar trait
pub struct TVar<'a, A: ?Sized> {
    //TODO add in mutex/cv pair for waiting for explicit aborts
    //This includes an explicit abort() command (as opposed to failing validation,
    //which should cause an immediate retry).
    version : AtomicUsize,
    //TODO this can be of lifetime 'b : 'a
    waiters : Mutex<Vec<Arc<(Mutex<bool>, Condvar)>>>,
    global : &'a GlobalState,
    val : UnsafeCell<A>,
}

impl<'a, A: ?Sized> TVar<'a, A> {
    unsafe fn get_val(&self) -> &A {
        &*self.val.get()
    }

    unsafe fn get_val_mut(&self) -> &mut A {
        &mut *self.val.get()
    }
}

impl<'a, A> TVar<'a, A> {
    unsafe fn to_addr<'b>(&'b self) -> TVarAddr<'b, 'a> {
        use std::raw::Slice;
        let fat_ptr = Slice::<u8> {
            data: transmute(self),
            len: size_of_val(self),
        };
        //let ptr : &*mut TVar<'a, [u8]> = transmute(self));
        TVarAddr {
            align: align_of::<A>(),
            addr: transmute(fat_ptr),
        }
    }

    ///TODO: change trait API to use this signature
    fn read<'l, 'b> (&'b mut self, l: &'l mut LocalState<'b, 'a>) -> Result<&'l A> {
        l.read(self)
    }

}
impl<'a, A : Copy> TVar<'a, A> {
    ///TODO: change trait API to use this signature
    fn write<'l, 'b>(&'b mut self, l: &'l mut LocalState<'b, 'a>, arg : A) -> Result<()> {
        l.write(self, arg)
    }
}

#[derive(Copy, Clone)]
/// Lies... Lies
struct TVarAddr<'a, 'b : 'a> {
    align: usize,
    addr: &'a TVar<'b, [u8]>, //*mut
    //_phan: PhantomData<&'a TVar<'b, ()>>,
}

impl<'a, 'b : 'a> Hash for TVarAddr<'a, 'b> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.raw_addr().hash(state);
    }
}

impl<'a, 'b : 'a> Eq for TVarAddr<'a, 'b> {}

impl<'a, 'b : 'a> PartialEq for TVarAddr<'a, 'b> {
    fn eq(&self, other: &Self) -> bool {
        let c = self.raw_addr() == other.raw_addr();
        if c {
            debug_assert_eq!(self.raw_len(), other.raw_len());
            debug_assert_eq!(self.align, other.align);
        }
        c
    }
}

impl<'a, 'b : 'a> TVarAddr<'a, 'b> {
    fn raw_addr(self) -> usize {
        self.addr as *const _ as *const () as usize
    }

    fn raw_len(self) -> usize {
        let y = self.addr.val.get();
        unsafe { transmute::<_,&[u8]>(y).len() }
    }

    unsafe fn aligned_mem(self) -> &'a mut [u8] {
        let buf = self.addr.val.get();
        let p = buf as *mut () as usize;
        // Assumes alignment is power of 2
        let o = ((p + (self.align - 1)) & self.align) - p;
        &mut (*buf)[o..]
    }

    fn version(self) -> &'a AtomicUsize {
        &(*self.addr).version
    }

    fn waiters(self) -> &'a mut Vec<(&'b Mutex<bool>, &'b Condvar)> {
        panic!("nyi")
    }
}

pub fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}
<commit_msg>removed irrelevant comment<commit_after>//#![allow(unused)]

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Condvar, Mutex, Arc};
use std::vec::Vec;
use std::collections::HashMap;
use std::cell::UnsafeCell;
use std::hash::{Hash, Hasher};
use std::mem::{align_of, size_of_val, transmute};
use std::slice::bytes::copy_memory;

use ::Result;

pub struct GlobalState { version : AtomicUsize }

/// Baseline implementation of GlobalState, currently do not hqve the aid of the compiler, so this
/// may have major issues.
/// TODO: make a proper implementation of the GlobalState trait
impl GlobalState {
    fn newLocal<'l, 'g>(&'g self) -> LocalState<'l, 'g> {
        LocalState {
            reads: Vec::new(),
            writes: HashMap::new(),
            global: self,
            snapshot: self.version.load(Ordering::SeqCst),
        }
    }

    pub fn retry<A, F>(&self, l: &mut LocalState, mut func: F) -> A
    where F: FnMut(&mut LocalState) -> Result<A> {
        let bx = Arc::new((Mutex::new(false), Condvar::new()));
        for &(addr, size) in &l.reads {
            let mut waiters = addr.addr.waiters.lock().unwrap();
            // this is actually unsafe...
            // maybe protect waiters with a lock
            waiters.push(bx.clone());
            //addr.waiters().push((&mtx, &cv));
        }
        let (ref mtx, ref cv) = *bx;
        let mut done = mtx.lock().unwrap();
        while !*done {
            done = cv.wait(done).unwrap();
        }
        self.run(func)
    }

    pub fn run<A, F>(&self, mut func : F) -> A
    where F: FnMut(&mut LocalState) -> Result<A> {
        let mut local = self.newLocal();
        match func(&mut local).spec_move() {
            Ok(r) => r,
            _ => self.run(func)
        }
    }

    pub fn or_else<A, F, G>(&self, mut func1 : F, func2 : G) -> A
        where F: FnMut(&mut LocalState) -> Result<A>,
              G: FnMut(&mut LocalState) -> Result<A> {
            let mut local1 = self.newLocal();
            match func1(&mut local1).spec_move() {
                Ok(r) => r,
                //TODO: this may not work, compiler may not know that
                //local1, which borrows self, has relinquised ownership
                _ => self.run(func2)
            }
    }
}

pub struct LocalState<'v, 'g : 'v> {
    /// the norec paper has the reads stored as a list of <address, value> pairs. For us it
    /// would probably be better to have versioned TVars. That way we always have a fast
    /// comparison operation and avoid doing extra dynamic dispatch when validating reads.
    reads : Vec<(TVarAddr<'v, 'g>, usize)>,

    /// for writes we will probably have to cast unsafely to get this to work. TVars just hold
    /// arbitrary types and we only have one table.  XXX: gross
    writes : HashMap<TVarAddr<'v, 'g>, Box<[u8]>>,

    /// STM environment we are using
    /// TODO: how are we getting away with this not being a mutable reference?
    global : &'g GlobalState,

    /// last version at which our view of the global state was valid
    snapshot : usize
}

impl<'v, 'g : 'v> LocalState<'v, 'g> {

    /// Validate the current local state against the state of the world,
    /// Aborts if a TVar in our readset has been written, otherwise
    /// returns the version number to with we are consistent
    pub fn validate(&self) -> Result<usize> {
        loop {
            let time = self.global.version.load(Ordering::SeqCst);
            if (time & 1) == 0 {
                continue;
            }
            for &(addr, version) in &self.reads {
                if addr.version().load(Ordering::SeqCst) != version {
                    return Result::abort();
                }
            }
            return Result::ret(time);
        }
    }

    /// Acquire reference to value in TVar within the transaction
    pub fn read<'l, A>(&'l mut self, tvar : &'v TVar<'g, A>) -> Result<&'l A>
        where 'v : 'l
    {
        let addr: TVarAddr<'v, 'g> = unsafe { tvar.to_addr() } ;

        // Should be &&'l ?
        if let Some(v) = self.writes.get(&addr) {
            let r : && [u8] = &&**v;
            assert_eq!(r.len(), ::std::mem::size_of::<A>());
            let r2 : && A = unsafe { transmute(r) };
            return Result::ret(r2)
        }

        if self.snapshot == self.global.version.load(Ordering::SeqCst) {
            self.reads.push((addr, tvar.version.load(Ordering::SeqCst)));
            Result::ret(unsafe {tvar.get_val()})
        } else {
            self.validate().bind( | v | {
                assert!(self.snapshot <= v);
                self.snapshot = v;
                self.reads.push((addr, tvar.version.load(Ordering::SeqCst)));
                Result::ret(unsafe {tvar.get_val()})
            })
        }
    }

    /// Add the TVar and value to our writeset, these are thread-local until the
    /// transaction commits
    pub fn write<A : Copy>(&mut self, tvar : &'v mut TVar<'g, A>, val : A) -> Result<()> {
        let b : Box<[A]> = Box::new([val]);
        unsafe {
            self.writes.insert(tvar.to_addr(), transmute(b));
        }
        Result::ret(())
    }

    /// if (read−only transaction)
    ///     return
    /// while (!CAS(&global lock, snapshot, snapshot + 1))
    ///     snapshot = Validate()
    /// for each (addr, val) in writes
    ///     ∗addr = val
    /// global lock = snapshot + 2 // one more than CAS above
    pub fn commit(&mut self) -> Result<()> {
        fn commit_loop(l : &mut LocalState) -> Result<()> {
            if l.global
                .version
                .compare_and_swap(l.snapshot, l.snapshot + 1, Ordering::SeqCst) == l.snapshot {
                Result::ret(())
            } else {
                l.validate().bind(|v| {
                    l.snapshot = v;
                    commit_loop(l)
                })
            }
        }
        if self.writes.is_empty() {
            Result::ret(())
        } else {
            commit_loop(self).bind(| _ | {
                for (mut addr, value) in &self.writes {
                    let dst = unsafe { addr.aligned_mem() };
                    debug_assert_eq!(value.len(), dst.len());
                    copy_memory(value, dst);
                    addr.addr.version.fetch_add(1, Ordering::SeqCst);
                    //TODO: DCLP if this is too slow in the common case that waiters is empty
                    let mut waiters = addr.addr.waiters.lock().unwrap();
                    for bx in &*waiters {
                        let (ref mtx, ref cv) = **bx;
                        let mut done = mtx.lock().unwrap();
                        *done = true;
                        cv.notify_all();
                    }
                    // this is safe because we hold the sequence lock
                    waiters.clear();
                    //addr.waiters().clear();
                    //TODO: set waiters to empty
                }
                self.global
                    .version
                    .compare_and_swap(self.snapshot + 1, self.snapshot + 2, Ordering::SeqCst);
                Result::ret(())
            })
        }
    }
}

/// Haskell-style container of mutable state within a transaction
/// TODO: impl TVar trait
pub struct TVar<'a, A: ?Sized> {
    //TODO add in mutex/cv pair for waiting for explicit aborts
    //This includes an explicit abort() command (as opposed to failing validation,
    //which should cause an immediate retry).
    version : AtomicUsize,
    //TODO this can be of lifetime 'b : 'a
    waiters : Mutex<Vec<Arc<(Mutex<bool>, Condvar)>>>,
    global : &'a GlobalState,
    val : UnsafeCell<A>,
}

impl<'a, A: ?Sized> TVar<'a, A> {
    unsafe fn get_val(&self) -> &A {
        &*self.val.get()
    }

    unsafe fn get_val_mut(&self) -> &mut A {
        &mut *self.val.get()
    }
}

impl<'a, A> TVar<'a, A> {
    unsafe fn to_addr<'b>(&'b self) -> TVarAddr<'b, 'a> {
        use std::raw::Slice;
        let fat_ptr = Slice::<u8> {
            data: transmute(self),
            len: size_of_val(self),
        };
        //let ptr : &*mut TVar<'a, [u8]> = transmute(self));
        TVarAddr {
            align: align_of::<A>(),
            addr: transmute(fat_ptr),
        }
    }

    ///TODO: change trait API to use this signature
    fn read<'l, 'b> (&'b mut self, l: &'l mut LocalState<'b, 'a>) -> Result<&'l A> {
        l.read(self)
    }

}
impl<'a, A : Copy> TVar<'a, A> {
    ///TODO: change trait API to use this signature
    fn write<'l, 'b>(&'b mut self, l: &'l mut LocalState<'b, 'a>, arg : A) -> Result<()> {
        l.write(self, arg)
    }
}

#[derive(Copy, Clone)]
/// Lies... Lies
struct TVarAddr<'a, 'b : 'a> {
    align: usize,
    addr: &'a TVar<'b, [u8]>, //*mut
    //_phan: PhantomData<&'a TVar<'b, ()>>,
}

impl<'a, 'b : 'a> Hash for TVarAddr<'a, 'b> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.raw_addr().hash(state);
    }
}

impl<'a, 'b : 'a> Eq for TVarAddr<'a, 'b> {}

impl<'a, 'b : 'a> PartialEq for TVarAddr<'a, 'b> {
    fn eq(&self, other: &Self) -> bool {
        let c = self.raw_addr() == other.raw_addr();
        if c {
            debug_assert_eq!(self.raw_len(), other.raw_len());
            debug_assert_eq!(self.align, other.align);
        }
        c
    }
}

impl<'a, 'b : 'a> TVarAddr<'a, 'b> {
    fn raw_addr(self) -> usize {
        self.addr as *const _ as *const () as usize
    }

    fn raw_len(self) -> usize {
        let y = self.addr.val.get();
        unsafe { transmute::<_,&[u8]>(y).len() }
    }

    unsafe fn aligned_mem(self) -> &'a mut [u8] {
        let buf = self.addr.val.get();
        let p = buf as *mut () as usize;
        // Assumes alignment is power of 2
        let o = ((p + (self.align - 1)) & self.align) - p;
        &mut (*buf)[o..]
    }

    fn version(self) -> &'a AtomicUsize {
        &(*self.addr).version
    }

    fn waiters(self) -> &'a mut Vec<(&'b Mutex<bool>, &'b Condvar)> {
        panic!("nyi")
    }
}

pub fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}
<|endoftext|>


<commit_before>use std::iter;

/// The representation of a possible value of an argument.
///
/// This is used for specifying [possible values] of [Args].
///
/// **NOTE:** This struct is likely not needed for most usecases as it is only required to
/// [hide] single values from help messages and shell completions or to attach [about] to possible values.
///
/// # Examples
///
/// ```rust
/// # use clap::{Arg, ArgValue};
/// let cfg = Arg::new("config")
///       .takes_value(true)
///       .value_name("FILE")
///       .possible_value(ArgValue::new("fast"))
///       .possible_value(ArgValue::new("slow").about("slower than fast"))
///       .possible_value(ArgValue::new("secret speed").hidden(true));
/// ```
/// [Args]: crate::Arg
/// [possible values]: crate::Arg::possible_value()
/// [hide]: ArgValue::hidden()
/// [about]: ArgValue::about()
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct ArgValue<'help> {
    pub(crate) name: &'help str,
    pub(crate) about: Option<&'help str>,
    pub(crate) aliases: Vec<&'help str>, // (name, visible)
    pub(crate) hidden: bool,
}

impl<'help> From<&'help str> for ArgValue<'help> {
    fn from(s: &'help str) -> Self {
        Self::new(s)
    }
}

/// Getters
impl<'help> ArgValue<'help> {
    /// Get the name of the argument value
    #[inline]
    pub fn get_name(&self) -> &str {
        self.name
    }

    /// Get the help specified for this argument, if any
    #[inline]
    pub fn get_about(&self) -> Option<&str> {
        self.about
    }

    /// Should the value be hidden from help messages and completion
    #[inline]
    pub fn is_hidden(&self) -> bool {
        self.hidden
    }

    /// Get the name if argument value is not hidden, `None` otherwise
    pub fn get_visible_name(&self) -> Option<&str> {
        if self.hidden {
            None
        } else {
            Some(self.name)
        }
    }

    /// TODO
    pub fn get_name_and_aliases(&self) -> impl Iterator<Item = &str> {
        iter::once(&self.name).chain(&self.aliases).copied()
    }

    /// TODO
    pub fn matches(&self, value: &str, ignore_case: bool) -> bool {
        if ignore_case {
            self.get_name_and_aliases()
                .any(|name| name.eq_ignore_ascii_case(value))
        } else {
            self.get_name_and_aliases().any(|name| name == value)
        }
    }
}

impl<'help> ArgValue<'help> {
    /// Creates a new instance of [`ArgValue`] using a string name. The name will be used to
    /// decide wether this value was provided by the user to an argument.
    ///
    /// **NOTE:** In case it is not [hidden] it will also be shown in help messages for arguments
    /// that use it as a [possible value] and have not hidden them through [`Arg::hide_possible_values(true)`].
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use clap::ArgValue;
    /// ArgValue::new("fast")
    /// # ;
    /// ```
    /// [hidden]: ArgValue::hidden
    /// [possible value]: crate::Arg::possible_values
    /// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values()
    pub fn new(name: &'help str) -> Self {
        ArgValue {
            name,
            ..Default::default()
        }
    }

    /// Sets the help text of the value that will be displayed to the user when completing the
    /// value in a compatible shell. Typically, this is a short description of the value.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use clap::ArgValue;
    /// ArgValue::new("slow")
    ///     .about("not fast")
    /// # ;
    /// ```
    #[inline]
    pub fn about(mut self, about: &'help str) -> Self {
        self.about = Some(about);
        self
    }

    /// Hides this value from help text and shell completions.
    ///
    /// This is an alternative to hiding through [`Arg::hide_possible_values(true)`], if you only
    /// want to hide some values.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use clap::ArgValue;
    /// ArgValue::new("secret")
    ///     .hidden(true)
    /// # ;
    /// ```
    /// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values()
    #[inline]
    pub fn hidden(mut self, yes: bool) -> Self {
        self.hidden = yes;
        self
    }

    /// TODO
    pub fn alias(mut self, name: &'help str) -> Self {
        self.aliases.push(name);
        self
    }

    /// TODO
    pub fn aliases<I>(mut self, names: I) -> Self
    where
        I: IntoIterator<Item = &'help str>,
    {
        self.aliases.extend(names.into_iter());
        self
    }
}
<commit_msg>documentation for ArgValue<commit_after>use std::iter;

/// The representation of a possible value of an argument.
///
/// This is used for specifying [possible values] of [Args].
///
/// **NOTE:** This struct is likely not needed for most usecases as it is only required to
/// [hide] single values from help messages and shell completions or to attach [about] to possible values.
///
/// # Examples
///
/// ```rust
/// # use clap::{Arg, ArgValue};
/// let cfg = Arg::new("config")
///       .takes_value(true)
///       .value_name("FILE")
///       .possible_value(ArgValue::new("fast"))
///       .possible_value(ArgValue::new("slow").about("slower than fast"))
///       .possible_value(ArgValue::new("secret speed").hidden(true));
/// ```
/// [Args]: crate::Arg
/// [possible values]: crate::Arg::possible_value()
/// [hide]: ArgValue::hidden()
/// [about]: ArgValue::about()
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct ArgValue<'help> {
    pub(crate) name: &'help str,
    pub(crate) about: Option<&'help str>,
    pub(crate) aliases: Vec<&'help str>, // (name, visible)
    pub(crate) hidden: bool,
}

impl<'help> From<&'help str> for ArgValue<'help> {
    fn from(s: &'help str) -> Self {
        Self::new(s)
    }
}

/// Getters
impl<'help> ArgValue<'help> {
    /// Get the name of the argument value
    #[inline]
    pub fn get_name(&self) -> &str {
        self.name
    }

    /// Get the help specified for this argument, if any
    #[inline]
    pub fn get_about(&self) -> Option<&str> {
        self.about
    }

    /// Should the value be hidden from help messages and completion
    #[inline]
    pub fn is_hidden(&self) -> bool {
        self.hidden
    }

    /// Get the name if argument value is not hidden, `None` otherwise
    pub fn get_visible_name(&self) -> Option<&str> {
        if self.hidden {
            None
        } else {
            Some(self.name)
        }
    }

    /// Returns all valid values of the argument value.
    /// Namely the name and all aliases.
    pub fn get_name_and_aliases(&self) -> impl Iterator<Item = &str> {
        iter::once(&self.name).chain(&self.aliases).copied()
    }

    /// Tests if the value is valid for this argument value
    ///
    /// The value is valid if it is either the name or one of the aliases.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use clap::ArgValue;
    /// let arg_value = ArgValue::new("fast").alias("not-slow");
    ///
    /// assert!(arg_value.matches("fast", false));
    /// assert!(arg_value.matches("not-slow", false));
    ///
    /// assert!(arg_value.matches("FAST", true));
    /// assert!(!arg_value.matches("FAST", false));
    /// ```
    pub fn matches(&self, value: &str, ignore_case: bool) -> bool {
        if ignore_case {
            self.get_name_and_aliases()
                .any(|name| name.eq_ignore_ascii_case(value))
        } else {
            self.get_name_and_aliases().any(|name| name == value)
        }
    }
}

impl<'help> ArgValue<'help> {
    /// Creates a new instance of [`ArgValue`] using a string name. The name will be used to
    /// decide wether this value was provided by the user to an argument.
    ///
    /// **NOTE:** In case it is not [hidden] it will also be shown in help messages for arguments
    /// that use it as a [possible value] and have not hidden them through [`Arg::hide_possible_values(true)`].
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use clap::ArgValue;
    /// ArgValue::new("fast")
    /// # ;
    /// ```
    /// [hidden]: ArgValue::hidden
    /// [possible value]: crate::Arg::possible_values
    /// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values()
    pub fn new(name: &'help str) -> Self {
        ArgValue {
            name,
            ..Default::default()
        }
    }

    /// Sets the help text of the value that will be displayed to the user when completing the
    /// value in a compatible shell. Typically, this is a short description of the value.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use clap::ArgValue;
    /// ArgValue::new("slow")
    ///     .about("not fast")
    /// # ;
    /// ```
    #[inline]
    pub fn about(mut self, about: &'help str) -> Self {
        self.about = Some(about);
        self
    }

    /// Hides this value from help text and shell completions.
    ///
    /// This is an alternative to hiding through [`Arg::hide_possible_values(true)`], if you only
    /// want to hide some values.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use clap::ArgValue;
    /// ArgValue::new("secret")
    ///     .hidden(true)
    /// # ;
    /// ```
    /// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values()
    #[inline]
    pub fn hidden(mut self, yes: bool) -> Self {
        self.hidden = yes;
        self
    }

    /// Sets an alias for this argument value.
    ///
    /// The alias will be hidden from completion and help texts.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use clap::ArgValue;
    /// ArgValue::new("slow")
    ///     .alias("not-fast")
    /// # ;
    /// ```
    pub fn alias(mut self, name: &'help str) -> Self {
        self.aliases.push(name);
        self
    }

    /// Sets multiple aliases for this argument value.
    ///
    /// The aliases will be hidden from completion and help texts.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use clap::ArgValue;
    /// ArgValue::new("slow")
    ///     .aliases(["not-fast", "snake-like"])
    /// # ;
    /// ```
    pub fn aliases<I>(mut self, names: I) -> Self
    where
        I: IntoIterator<Item = &'help str>,
    {
        self.aliases.extend(names.into_iter());
        self
    }
}
<|endoftext|>


<commit_before>use codemap::Spanned;
use lexer::Token;
use std::iter::Peekable;
use std::slice::Iter;
use self::ParseErrorKind::*;

type ParseIter<'a> = Peekable<Iter<'a, Spanned<Token>>>;
type Parse = Result<Node, ParseErrorKind>;

#[derive(Debug, Clone, PartialEq)]
pub enum Node {
  Block(Vec<Node>),
  If {
    cond: Box<Node>,
  },
  Stmt(Box<Node>),
  Break,
  Continue,
  Expr,
  Pass,
  Index {
    lhs: Box<Node>,
    rhs: Box<Node>,
  },

  Method {
    owner: Box<Node>,
    method: Box<Node>,
    args: Vec<Node>,
  },

  Lambda {
    params: Vec<String>,
    expr: Box<Node>,
  },

  Func {
    func: Box<Node>,
    args: Vec<Node>,
  },

  BinExpr {
    lhs: Box<Node>,
    op: Token,
    rhs: Box<Node>,
  },

  UnExpr {
    val: Box<Node>,
    op: Token,
  },

  // Literals
  Null,
  Bool(bool),
  Float(f64),
  Int(i64),
  Str(String),
  Name(String),
  Table,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Op {
  Right(u32),
  Left(u32),
  None,
}

#[derive(Debug, Clone, PartialEq)]
pub enum ParseErrorKind {
  UnexpectedToken(Token),
  UnexpectedEOF,
  UnknownBinaryOperator,
  UnknownUnaryOperator,
}

// Return true if the next token in `it` is `kind`
fn peek_token(it: &mut ParseIter, kind: Token) -> bool {
  if let Some(&tok) = it.peek() {
    tok.node == kind
  } else {
    false
  }
}

// Return true if the next token in `it` is `kind` *and* consume the token
fn use_token(it: &mut ParseIter, kind: Token) -> bool {
  if let Some(&tok) = it.peek() {
    if tok.node == kind {
      it.next();
    }
    tok.node == kind
  } else {
    false
  }
}

// Panic if the next token in `it` is *not* `kind`
fn require_token(it: &mut ParseIter, kind: Token) -> Result<(), ParseErrorKind> {
  if let Some(&tok) = it.peek() {
    if tok.node == kind {
      it.next();
      return Ok(());
    }

    return Err(UnexpectedToken(tok.node.clone()));
  }

  return Err(UnexpectedEOF);
}

fn op_precedence(op: &Token) -> Op {
  match *op {
    Token::Add | Token::Sub => Op::Left(10),
    Token::Div | Token::Mul => Op::Left(20),
    Token::Car => Op::Right(30),
    _ => Op::None,
  }
}

fn parse_il_expr(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Or => {
        it.next();
        let params = parse_fn_params(it)?;
        require_token(it, Token::Or)?;
        let expr = parse_il_expr(it)?;
        Ok(Node::Lambda {
          params: params,
          expr: Box::new(expr),
        })
      }
      _ => parse_bin_expr(it),
    };
  }

  Err(UnexpectedEOF)
}

fn parse_bin_expr(it: &mut ParseIter) -> Parse {
  let mut expr = parse_un_expr(it)?;

  // prevents this from breaking the LHS until we know we made it
  // otherwise, things like (2 + 3) * 4 get restructured into 2 + (3 * 4)
  let mut break_left = false;

  while let Some(&tok) = it.peek() {
    let prec = op_precedence(&tok.node);

    if let Op::None = prec {
      break;
    }

    it.next();

    let rhs = parse_un_expr(it)?;

    expr = match (break_left, expr.clone()) {
      (
        true,
        Node::BinExpr {
          lhs: cur_lhs,
          op: cur_op,
          rhs: cur_rhs,
        },
      ) => {
        let cur_prec = op_precedence(&cur_op);
        match (cur_prec, prec) {
          // these should never happen
          (_, Op::None) => break,
          (Op::None, _) => break,

          // left-to-right
          // there has to be a better way to handle this, no?
          (Op::Left(n), Op::Left(m)) if n >= m => Node::BinExpr {
            lhs: Box::new(expr),
            op: tok.node.clone(),
            rhs: Box::new(rhs),
          },
          (Op::Right(n), Op::Right(m)) if n > m => Node::BinExpr {
            lhs: Box::new(expr),
            op: tok.node.clone(),
            rhs: Box::new(rhs),
          },
          (Op::Right(n), Op::Left(m)) if n >= m => Node::BinExpr {
            lhs: Box::new(expr),
            op: tok.node.clone(),
            rhs: Box::new(rhs),
          },
          (Op::Left(n), Op::Right(m)) if n >= m => Node::BinExpr {
            lhs: Box::new(expr),
            op: tok.node.clone(),
            rhs: Box::new(rhs),
          },

          // right-to-left
          _ => Node::BinExpr {
            lhs: cur_lhs,
            op: cur_op,
            rhs: Box::new(Node::BinExpr {
              lhs: cur_rhs,
              op: tok.node.clone(),
              rhs: Box::new(rhs),
            }),
          },
        }
      }
      _ => Node::BinExpr {
        lhs: Box::new(expr),
        op: tok.node.clone(),
        rhs: Box::new(rhs),
      },
    };

    break_left = true;
  }

  Ok(expr)
}

fn parse_un_expr(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Sub | Token::Not | Token::Neg => {
        it.next();
        let val = parse_un_expr(it)?;
        Ok(Node::UnExpr {
          op: tok.node.clone(),
          val: Box::new(val),
        })
      }
      _ => parse_simple(it),
    };
  }

  Err(UnexpectedEOF)
}

/* unused, here for reference
fn parse_index(it: &mut ParseIter) -> Parse {
  if let Some(&c) = it.peek() {
    return match c.node {
      Token::Sql => {
        it.next();
        let idx = parse_bin_expr(it)?;
        require_token(it, Token::Sqr)?;
        Ok(idx)
      }
      Token::Dot => {
        it.next();
        parse_name_as_str(it)
      }
      _ => {
        Err(UnexpectedToken(c.node.clone()))
      }
    };
  }

  Err(UnexpectedEOF)
}
*/

fn parse_fn_params(it: &mut ParseIter) -> Result<Vec<String>, ParseErrorKind> {
  let mut params: Vec<String> = Vec::new();
  while let Some(&tok) = it.peek() {
    match tok.node {
      Token::Name(ref x) => {
        it.next();
        params.push(x.to_string());
        if !use_token(it, Token::Com) {
          break;
        }
      }
      _ => break,
    }
  }

  Ok(params)
}

fn parse_fn_args(it: &mut ParseIter) -> Result<Vec<Node>, ParseErrorKind> {
  require_token(it, Token::Pal)?;
  // FIXME
  require_token(it, Token::Par)?;
  Ok(Vec::new())
}

fn parse_simple(it: &mut ParseIter) -> Parse {
  let mut atom = parse_atom(it)?;
  while let Some(&tok) = it.peek() {
    match tok.node {
      Token::Col => {
        it.next();
        let method = parse_name_as_str(it)?;
        let args = parse_fn_args(it)?;
        atom = Node::Method {
          owner: Box::new(atom),
          method: Box::new(method),
          args: args,
        };
      }

      Token::Pal => {
        let args = parse_fn_args(it)?;
        atom = Node::Func {
          func: Box::new(atom),
          args: args,
        };
      }

      Token::Sql => {
        it.next();
        let idx = parse_bin_expr(it)?;
        require_token(it, Token::Sqr)?;
        atom = Node::Index {
          lhs: Box::new(atom),
          rhs: Box::new(idx),
        };
      }

      Token::Dot => {
        it.next();
        let idx = parse_name_as_str(it)?;
        atom = Node::Index {
          lhs: Box::new(atom),
          rhs: Box::new(idx),
        };
      }

      _ => break,
    }
  }

  Ok(atom)
}

fn parse_atom(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Pal => {
        it.next();
        let out = parse_bin_expr(it)?;
        require_token(it, Token::Par)?;
        Ok(out)
      }
      _ => parse_quark(it),
    };
  }

  Err(UnexpectedEOF)
}

fn parse_name_as_str(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Name(ref x) => {
        it.next();
        Ok(Node::Str(x.clone()))
      }
      ref x => Err(UnexpectedToken(x.clone())),
    };
  }

  Err(UnexpectedEOF)
}

fn parse_name(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Name(ref x) => {
        it.next();
        Ok(Node::Name(x.clone()))
      }
      ref x => Err(UnexpectedToken(x.clone())),
    };
  }

  Err(UnexpectedEOF)
}

fn parse_quark(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Null => {
        it.next();
        Ok(Node::Null)
      }
      Token::Bool(x) => {
        it.next();
        Ok(Node::Bool(x))
      }
      Token::Float(x) => {
        it.next();
        Ok(Node::Float(x))
      }
      Token::Int(x) => {
        it.next();
        Ok(Node::Int(x))
      }
      Token::Str(ref x) => {
        it.next();
        Ok(Node::Str(x.clone()))
      }
      Token::Name(ref x) => {
        it.next();
        Ok(Node::Name(x.clone()))
      }
      Token::Table => {
        it.next();
        Ok(Node::Table)
      }
      ref x => Err(UnexpectedToken(x.clone())),
    };
  }

  Err(UnexpectedEOF)
}

fn parse_stmt(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Break => {
        it.next();
        Ok(Node::Break)
      }

      Token::Continue => {
        it.next();
        Ok(Node::Continue)
      }

      Token::Pass => {
        it.next();
        Ok(Node::Pass)
      }

      _ => parse_bin_expr(it).map(|expr| Node::Stmt(Box::new(expr))),
    };
  }

  Err(UnexpectedEOF)
}

pub fn parse(tokens: Vec<Spanned<Token>>) -> Parse {
  let mut it: ParseIter = tokens.iter().peekable();
  let mut nodes: Vec<Node> = vec![];

  while !peek_token(&mut it, Token::EOF) {
    nodes.push(parse_stmt(&mut it)?);
    require_token(&mut it, Token::End)?;
  }

  Ok(Node::Block(nodes))
}

#[cfg(test)]
#[path = "./tests/parser.rs"]
mod tests;
<commit_msg>parser: Use parse_il_expr for statements<commit_after>use codemap::Spanned;
use lexer::Token;
use std::iter::Peekable;
use std::slice::Iter;
use self::ParseErrorKind::*;

type ParseIter<'a> = Peekable<Iter<'a, Spanned<Token>>>;
type Parse = Result<Node, ParseErrorKind>;

#[derive(Debug, Clone, PartialEq)]
pub enum Node {
  Block(Vec<Node>),
  If {
    cond: Box<Node>,
  },
  Stmt(Box<Node>),
  Break,
  Continue,
  Expr,
  Pass,
  Index {
    lhs: Box<Node>,
    rhs: Box<Node>,
  },

  Method {
    owner: Box<Node>,
    method: Box<Node>,
    args: Vec<Node>,
  },

  Lambda {
    params: Vec<String>,
    expr: Box<Node>,
  },

  Func {
    func: Box<Node>,
    args: Vec<Node>,
  },

  BinExpr {
    lhs: Box<Node>,
    op: Token,
    rhs: Box<Node>,
  },

  UnExpr {
    val: Box<Node>,
    op: Token,
  },

  // Literals
  Null,
  Bool(bool),
  Float(f64),
  Int(i64),
  Str(String),
  Name(String),
  Table,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Op {
  Right(u32),
  Left(u32),
  None,
}

#[derive(Debug, Clone, PartialEq)]
pub enum ParseErrorKind {
  UnexpectedToken(Token),
  UnexpectedEOF,
  UnknownBinaryOperator,
  UnknownUnaryOperator,
}

// Return true if the next token in `it` is `kind`
fn peek_token(it: &mut ParseIter, kind: Token) -> bool {
  if let Some(&tok) = it.peek() {
    tok.node == kind
  } else {
    false
  }
}

// Return true if the next token in `it` is `kind` *and* consume the token
fn use_token(it: &mut ParseIter, kind: Token) -> bool {
  if let Some(&tok) = it.peek() {
    if tok.node == kind {
      it.next();
    }
    tok.node == kind
  } else {
    false
  }
}

// Panic if the next token in `it` is *not* `kind`
fn require_token(it: &mut ParseIter, kind: Token) -> Result<(), ParseErrorKind> {
  if let Some(&tok) = it.peek() {
    if tok.node == kind {
      it.next();
      return Ok(());
    }

    return Err(UnexpectedToken(tok.node.clone()));
  }

  return Err(UnexpectedEOF);
}

fn op_precedence(op: &Token) -> Op {
  match *op {
    Token::Add | Token::Sub => Op::Left(10),
    Token::Div | Token::Mul => Op::Left(20),
    Token::Car => Op::Right(30),
    _ => Op::None,
  }
}

fn parse_il_expr(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Or => {
        it.next();
        let params = parse_fn_params(it)?;
        require_token(it, Token::Or)?;
        let expr = parse_il_expr(it)?;
        Ok(Node::Lambda {
          params: params,
          expr: Box::new(expr),
        })
      }
      _ => parse_bin_expr(it),
    };
  }

  Err(UnexpectedEOF)
}

fn parse_bin_expr(it: &mut ParseIter) -> Parse {
  let mut expr = parse_un_expr(it)?;

  // prevents this from breaking the LHS until we know we made it
  // otherwise, things like (2 + 3) * 4 get restructured into 2 + (3 * 4)
  let mut break_left = false;

  while let Some(&tok) = it.peek() {
    let prec = op_precedence(&tok.node);

    if let Op::None = prec {
      break;
    }

    it.next();

    let rhs = parse_un_expr(it)?;

    expr = match (break_left, expr.clone()) {
      (
        true,
        Node::BinExpr {
          lhs: cur_lhs,
          op: cur_op,
          rhs: cur_rhs,
        },
      ) => {
        let cur_prec = op_precedence(&cur_op);
        match (cur_prec, prec) {
          // these should never happen
          (_, Op::None) => break,
          (Op::None, _) => break,

          // left-to-right
          // there has to be a better way to handle this, no?
          (Op::Left(n), Op::Left(m)) if n >= m => Node::BinExpr {
            lhs: Box::new(expr),
            op: tok.node.clone(),
            rhs: Box::new(rhs),
          },
          (Op::Right(n), Op::Right(m)) if n > m => Node::BinExpr {
            lhs: Box::new(expr),
            op: tok.node.clone(),
            rhs: Box::new(rhs),
          },
          (Op::Right(n), Op::Left(m)) if n >= m => Node::BinExpr {
            lhs: Box::new(expr),
            op: tok.node.clone(),
            rhs: Box::new(rhs),
          },
          (Op::Left(n), Op::Right(m)) if n >= m => Node::BinExpr {
            lhs: Box::new(expr),
            op: tok.node.clone(),
            rhs: Box::new(rhs),
          },

          // right-to-left
          _ => Node::BinExpr {
            lhs: cur_lhs,
            op: cur_op,
            rhs: Box::new(Node::BinExpr {
              lhs: cur_rhs,
              op: tok.node.clone(),
              rhs: Box::new(rhs),
            }),
          },
        }
      }
      _ => Node::BinExpr {
        lhs: Box::new(expr),
        op: tok.node.clone(),
        rhs: Box::new(rhs),
      },
    };

    break_left = true;
  }

  Ok(expr)
}

fn parse_un_expr(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Sub | Token::Not | Token::Neg => {
        it.next();
        let val = parse_un_expr(it)?;
        Ok(Node::UnExpr {
          op: tok.node.clone(),
          val: Box::new(val),
        })
      }
      _ => parse_simple(it),
    };
  }

  Err(UnexpectedEOF)
}

/* unused, here for reference
fn parse_index(it: &mut ParseIter) -> Parse {
  if let Some(&c) = it.peek() {
    return match c.node {
      Token::Sql => {
        it.next();
        let idx = parse_bin_expr(it)?;
        require_token(it, Token::Sqr)?;
        Ok(idx)
      }
      Token::Dot => {
        it.next();
        parse_name_as_str(it)
      }
      _ => {
        Err(UnexpectedToken(c.node.clone()))
      }
    };
  }

  Err(UnexpectedEOF)
}
*/

fn parse_fn_params(it: &mut ParseIter) -> Result<Vec<String>, ParseErrorKind> {
  let mut params: Vec<String> = Vec::new();
  while let Some(&tok) = it.peek() {
    match tok.node {
      Token::Name(ref x) => {
        it.next();
        params.push(x.to_string());
        if !use_token(it, Token::Com) {
          break;
        }
      }
      _ => break,
    }
  }

  Ok(params)
}

fn parse_fn_args(it: &mut ParseIter) -> Result<Vec<Node>, ParseErrorKind> {
  require_token(it, Token::Pal)?;
  // FIXME
  require_token(it, Token::Par)?;
  Ok(Vec::new())
}

fn parse_simple(it: &mut ParseIter) -> Parse {
  let mut atom = parse_atom(it)?;
  while let Some(&tok) = it.peek() {
    match tok.node {
      Token::Col => {
        it.next();
        let method = parse_name_as_str(it)?;
        let args = parse_fn_args(it)?;
        atom = Node::Method {
          owner: Box::new(atom),
          method: Box::new(method),
          args: args,
        };
      }

      Token::Pal => {
        let args = parse_fn_args(it)?;
        atom = Node::Func {
          func: Box::new(atom),
          args: args,
        };
      }

      Token::Sql => {
        it.next();
        let idx = parse_bin_expr(it)?;
        require_token(it, Token::Sqr)?;
        atom = Node::Index {
          lhs: Box::new(atom),
          rhs: Box::new(idx),
        };
      }

      Token::Dot => {
        it.next();
        let idx = parse_name_as_str(it)?;
        atom = Node::Index {
          lhs: Box::new(atom),
          rhs: Box::new(idx),
        };
      }

      _ => break,
    }
  }

  Ok(atom)
}

fn parse_atom(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Pal => {
        it.next();
        let out = parse_bin_expr(it)?;
        require_token(it, Token::Par)?;
        Ok(out)
      }
      _ => parse_quark(it),
    };
  }

  Err(UnexpectedEOF)
}

fn parse_name_as_str(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Name(ref x) => {
        it.next();
        Ok(Node::Str(x.clone()))
      }
      ref x => Err(UnexpectedToken(x.clone())),
    };
  }

  Err(UnexpectedEOF)
}

fn parse_name(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Name(ref x) => {
        it.next();
        Ok(Node::Name(x.clone()))
      }
      ref x => Err(UnexpectedToken(x.clone())),
    };
  }

  Err(UnexpectedEOF)
}

fn parse_quark(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Null => {
        it.next();
        Ok(Node::Null)
      }
      Token::Bool(x) => {
        it.next();
        Ok(Node::Bool(x))
      }
      Token::Float(x) => {
        it.next();
        Ok(Node::Float(x))
      }
      Token::Int(x) => {
        it.next();
        Ok(Node::Int(x))
      }
      Token::Str(ref x) => {
        it.next();
        Ok(Node::Str(x.clone()))
      }
      Token::Name(ref x) => {
        it.next();
        Ok(Node::Name(x.clone()))
      }
      Token::Table => {
        it.next();
        Ok(Node::Table)
      }
      ref x => Err(UnexpectedToken(x.clone())),
    };
  }

  Err(UnexpectedEOF)
}

fn parse_stmt(it: &mut ParseIter) -> Parse {
  if let Some(&tok) = it.peek() {
    return match tok.node {
      Token::Break => {
        it.next();
        Ok(Node::Break)
      }

      Token::Continue => {
        it.next();
        Ok(Node::Continue)
      }

      Token::Pass => {
        it.next();
        Ok(Node::Pass)
      }

      _ => parse_il_expr(it).map(|expr| Node::Stmt(Box::new(expr))),
    };
  }

  Err(UnexpectedEOF)
}

pub fn parse(tokens: Vec<Spanned<Token>>) -> Parse {
  let mut it: ParseIter = tokens.iter().peekable();
  let mut nodes: Vec<Node> = vec![];

  while !peek_token(&mut it, Token::EOF) {
    nodes.push(parse_stmt(&mut it)?);
    require_token(&mut it, Token::End)?;
  }

  Ok(Node::Block(nodes))
}

#[cfg(test)]
#[path = "./tests/parser.rs"]
mod tests;
<|endoftext|>