<commit_before>//! This module provides an oct-tree of cubes. Each leaf cube describes a
//! spatial partition, its properties, and a deformable geometry.

extern crate nalgebra;
extern crate num;

use ::nalgebra::Origin;
use ::num::{One, Zero}; // TODO: `use ::std::num::{One, Zero};`.
use ::std::error;
use ::std::error::Error;
use ::std::fmt;
use ::std::mem;
use ::std::ops;

use math::{Clamp, Mask, DiscreteSpace};
use resource::ResourceId;

pub const MAX_WIDTH: RootWidth = 32;
pub const MIN_WIDTH: RootWidth = 4;

pub type Point3 = nalgebra::Point3<DiscreteSpace>;
pub type Vector3 = nalgebra::Vector3<DiscreteSpace>;
pub type RootWidth = u8; // TODO: https://github.com/rust-lang/rfcs/issues/671

impl Clamp<RootWidth> for RootWidth {
    fn clamp(&self, min: RootWidth, max: RootWidth) -> Self {
        nalgebra::clamp(*self, min, max)
    }
}

#[derive(Clone)]
pub struct Partition {
    origin: Point3,
    width: RootWidth,
}

impl Partition {
    fn at_point(point: &Point3, width: RootWidth) -> Self {
        Partition {
            origin: point.mask(!DiscreteSpace::zero() << width),
            width: width,
        }
    }

    fn at_index(&self, index: usize) -> Option<Self> {
        if self.width > MIN_WIDTH {
            let width = self.width - 1;
            Some(Partition {
                origin: self.origin + vector_at_index(index, width),
                width: width,
            })
        } else {
            None
        }
    }

    pub fn origin(&self) -> &Point3 {
        &self.origin
    }

    pub fn width(&self) -> RootWidth {
        self.width
    }

    pub fn midpoint(&self) -> Point3 {
        let m = exp(self.width - 1);
        Point3::new(m, m, m)
    }
}

pub trait ComputedCube: ops::Deref<Target = Cube> {
    fn partition(&self) -> &Partition;

    fn depth(&self) -> u8;
}

#[derive(Debug)]
pub enum JoinError {
    LeafJoined,
}

impl fmt::Display for JoinError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for JoinError {
    fn description(&self) -> &str {
        match *self {
            JoinError::LeafJoined => "attempted to join leaf",
        }
    }
}

#[derive(Debug)]
pub enum SubdivideError {
    LimitExceeded,
    BranchSubdivided,
}

impl fmt::Display for SubdivideError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for SubdivideError {
    fn description(&self) -> &str {
        match *self {
            SubdivideError::LimitExceeded => "minimum width limit exceeded",
            SubdivideError::BranchSubdivided => "attempted to subdivide branch",
        }
    }
}

pub trait ComputedCubeMut: ComputedCube + ops::DerefMut {
    fn join(&mut self) -> Result<&mut Self, JoinError> {
        try!(self.deref_mut().join().ok_or(JoinError::LeafJoined));
        Ok(self)
    }

    fn subdivide(&mut self) -> Result<&mut Self, SubdivideError> {
        if self.partition().width() > MIN_WIDTH {
            try!(self.deref_mut().subdivide().ok_or(SubdivideError::BranchSubdivided));
            Ok(self)
        } else {
            Err(SubdivideError::LimitExceeded)
        }
    }
}

#[derive(Clone)]
pub struct Traversal<'a> {
    cube: &'a Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> Traversal<'a> {
    fn new(cube: &'a Cube, root: &'a Partition, partition: Partition) -> Self {
        Traversal {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn iter(&self) -> CubeIter {
        CubeIter::new(self.clone())
    }

    pub fn at_point(&self, point: &Point3, width: RootWidth) -> Self {
        let mut cube = self.cube;
        let mut depth = self.partition.width();

        // Clamp the inputs.
        let point = point.clamp(0, (exp(self.root.width())) - 1);
        let width = exp(width.clamp(MIN_WIDTH, depth));

        while (width >> depth) == 0 {
            match *cube {
                Cube::Branch(ref branch) => {
                    depth = depth - 1;
                    cube = &branch.cubes[index_at_point(&point, depth)]
                }
                _ => break,
            }
        }

        Traversal::new(cube, self.root, Partition::at_point(&point, depth))
    }
}

impl<'a> ComputedCube for Traversal<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> ops::Deref for Traversal<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

pub struct CubeIter<'a> {
    traversals: Vec<Traversal<'a>>,
}

impl<'a> CubeIter<'a> {
    fn new(traversal: Traversal<'a>) -> Self {
        CubeIter { traversals: vec![traversal] }
    }
}

impl<'a> Iterator for CubeIter<'a> {
    type Item = Traversal<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(traversal) = self.traversals.pop() {
            match *traversal.cube {
                Cube::Branch(ref branch) => {
                    for (index, cube) in branch.iter().enumerate() {
                        self.traversals.push(Traversal::new(
                            cube,
                            traversal.root,
                            traversal.partition().at_index(index).unwrap()));
                    }
                }
                _ => {}
            }
            Some(traversal)
        } else {
            None
        }
    }
}

pub struct TraversalMut<'a> {
    cube: &'a mut Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> TraversalMut<'a> {
    fn new(cube: &'a mut Cube, root: &'a Partition, partition: Partition) -> Self {
        TraversalMut {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn at_point(&'a mut self, point: &Point3, width: RootWidth) -> Self {
        let mut cube: Option<&mut Cube> = Some(self.cube);
        let mut depth = self.partition.width();

        let point = point.clamp(0, (exp(self.root.width())) - 1);
        let width = exp(width.clamp(MIN_WIDTH, depth));

        while (width >> depth) == 0 {
            let inner = cube.take().unwrap();
            match *inner {
                Cube::Branch(ref mut branch) => {
                    depth = depth - 1;
                    cube = Some(&mut branch.cubes[index_at_point(&point, depth)]);
                }
                _ => {
                    cube = Some(inner);
                    break;
                }
            }
        }

        TraversalMut::new(cube.take().unwrap(),
                       self.root,
                       Partition::at_point(&point, depth))
    }
}

impl<'a> ComputedCube for TraversalMut<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> ComputedCubeMut for TraversalMut<'a> {}

impl<'a> ops::Deref for TraversalMut<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

impl<'a> ops::DerefMut for TraversalMut<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.cube
    }
}

pub struct Tree {
    cube: Cube,
    partition: Partition,
}

impl Tree {
    pub fn new(width: RootWidth) -> Self {
        Tree {
            cube: Cube::new(),
            partition: Partition::at_point(&Point3::origin(),
                                           width.clamp(MIN_WIDTH, MAX_WIDTH)),
        }
    }

    pub fn iter(&self) -> CubeIter {
        CubeIter::new(self.traverse())
    }

    pub fn traverse(&self) -> Traversal {
        Traversal::new(&self.cube, &self.partition, self.partition.clone())
    }

    pub fn traverse_mut(&mut self) -> TraversalMut {
        TraversalMut::new(&mut self.cube, &self.partition, self.partition.clone())
    }
}

impl ComputedCube for Tree {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        0
    }
}

impl ComputedCubeMut for Tree {}

impl ops::Deref for Tree {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        &self.cube
    }
}

impl ops::DerefMut for Tree {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.cube
    }
}

#[derive(Clone)]
pub enum Cube {
    Leaf(LeafNode),
    Branch(BranchNode),
}

impl Cube {
    fn new() -> Self {
        Cube::Leaf(LeafNode::new())
    }

    fn join(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Branch(branch) => {
                *self = branch.join().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    fn subdivide(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Leaf(leaf) => {
                *self = leaf.subdivide().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    pub fn is_leaf(&self) -> bool {
        match *self {
            Cube::Leaf(_) => true,
            _ => false,
        }
    }
}

impl Default for Cube {
    fn default() -> Self {
        Cube::new()
    }
}

impl From<LeafNode> for Cube {
    fn from(leaf: LeafNode) -> Self {
        Cube::Leaf(leaf)
    }
}

impl From<BranchNode> for Cube {
    fn from(branch: BranchNode) -> Self {
        Cube::Branch(branch)
    }
}

#[derive(Clone, Copy)]
pub struct LeafNode {
    pub geometry: Geometry,
    pub material: ResourceId,
}

impl LeafNode {
    fn new() -> Self {
        LeafNode {
            geometry: Geometry::full(),
            material: 0,
        }
    }

    fn subdivide(self) -> BranchNode {
        // TODO: Transform the geometry of the parent into the children.
        let cube: Cube = self.into();
        BranchNode {
            cubes: Box::new([cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube]),
        }
    }
}

pub struct BranchNode {
    cubes: Box<[Cube; 8]>,
}

impl BranchNode {
    fn join(self) -> LeafNode {
        // TODO: Copy data from one of the original leaves.
        LeafNode::new()
    }
}

impl Clone for BranchNode {
    fn clone(&self) -> Self {
        BranchNode {
            cubes: Box::new([self.cubes[0].clone(),
                             self.cubes[1].clone(),
                             self.cubes[2].clone(),
                             self.cubes[3].clone(),
                             self.cubes[4].clone(),
                             self.cubes[5].clone(),
                             self.cubes[6].clone(),
                             self.cubes[7].clone()]),
        }
    }
}

impl ops::Deref for BranchNode {
    type Target = [Cube];

    fn deref(&self) -> &Self::Target {
        &*self.cubes
    }
}

#[derive(Copy, Clone)]
pub struct Geometry([[Edge; 4]; 3]);

impl Geometry {
    fn full() -> Self {
        Geometry([[Edge::full(); 4]; 3])
    }

    fn empty() -> Self {
        Geometry([[Edge::converged(0); 4]; 3])
    }

    pub fn as_edges_x(&self) -> &[Edge; 4] {
        &self.0[0]
    }
    pub fn as_edges_y(&self) -> &[Edge; 4] {
        &self.0[1]
    }
    pub fn as_edges_z(&self) -> &[Edge; 4] {
        &self.0[2]
    }

    pub fn as_edges_x_mut(&mut self) -> &mut [Edge; 4] {
        &mut self.0[0]
    }
    pub fn as_edges_y_mut(&mut self) -> &mut [Edge; 4] {
        &mut self.0[1]
    }
    pub fn as_edges_z_mut(&mut self) -> &mut [Edge; 4] {
        &mut self.0[2]
    }
}

#[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct Edge(u8);

const MIN_EDGE: u8 = 0;
const MAX_EDGE: u8 = 0x0F;

impl Edge {
    fn full() -> Self {
        Edge(MAX_EDGE)
    }

    fn converged(value: u8) -> Self {
        let value = nalgebra::clamp(value, MIN_EDGE, MAX_EDGE);
        Edge((value << 4) | value)
    }

    pub fn set_front(&mut self, value: u8) {
        let value = nalgebra::clamp(value, MIN_EDGE, self.back());
        self.0 = (value << 4) | self.back();
    }

    pub fn set_back(&mut self, value: u8) {
        let value = nalgebra::clamp(value, self.front(), MAX_EDGE);
        self.0 = (self.front() << 4) | value;
    }

    pub fn front(&self) -> u8 {
        (self.0 & 0xF0) >> 4
    }

    pub fn back(&self) -> u8 {
        self.0 & 0x0F
    }

    pub fn front_transform(&self) -> f32 {
        ((self.front() - MIN_EDGE) as f32) / ((MAX_EDGE - MIN_EDGE) as f32)
    }

    pub fn back_transform(&self) -> f32 {
        let range = MAX_EDGE - MIN_EDGE;
        -((range - (self.back() - MIN_EDGE)) as f32) / (range as f32)
    }
}

trait Subdivision {}

impl Subdivision for [Cube; 8] {}

trait Storage {}

impl Storage for Box<[Cube; 8]> {}

#[cfg_attr(rustfmt, rustfmt_skip)]
fn index_at_point(point: &Point3, width: RootWidth) -> usize {
    ((((point.x >> width) & DiscreteSpace::one()) << 0) |
     (((point.y >> width) & DiscreteSpace::one()) << 1) |
     (((point.z >> width) & DiscreteSpace::one()) << 2)) as usize
}

fn vector_at_index(index: usize, width: RootWidth) -> Vector3 {
    assert!(index < 8);
    let index = index as DiscreteSpace;
    let width = exp(width);
    Vector3::new(((index >> 0) & DiscreteSpace::one()) * width,
                 ((index >> 1) & DiscreteSpace::one()) * width,
                 ((index >> 2) & DiscreteSpace::one()) * width)
}

pub fn exp(width: RootWidth) -> DiscreteSpace {
    if width > 0 {
        DiscreteSpace::one() << (width - 1)
    } else {
        0
    }
}

#[cfg(test)]
mod tests {
    use super::*;
}
<commit_msg>Format code with rustfmt.<commit_after>//! This module provides an oct-tree of cubes. Each leaf cube describes a
//! spatial partition, its properties, and a deformable geometry.

extern crate nalgebra;
extern crate num;

use ::nalgebra::Origin;
use ::num::{One, Zero}; // TODO: `use ::std::num::{One, Zero};`.
use ::std::error;
use ::std::error::Error;
use ::std::fmt;
use ::std::mem;
use ::std::ops;

use math::{Clamp, Mask, DiscreteSpace};
use resource::ResourceId;

pub const MAX_WIDTH: RootWidth = 32;
pub const MIN_WIDTH: RootWidth = 4;

pub type Point3 = nalgebra::Point3<DiscreteSpace>;
pub type Vector3 = nalgebra::Vector3<DiscreteSpace>;
pub type RootWidth = u8; // TODO: https://github.com/rust-lang/rfcs/issues/671

impl Clamp<RootWidth> for RootWidth {
    fn clamp(&self, min: RootWidth, max: RootWidth) -> Self {
        nalgebra::clamp(*self, min, max)
    }
}

#[derive(Clone)]
pub struct Partition {
    origin: Point3,
    width: RootWidth,
}

impl Partition {
    fn at_point(point: &Point3, width: RootWidth) -> Self {
        Partition {
            origin: point.mask(!DiscreteSpace::zero() << width),
            width: width,
        }
    }

    fn at_index(&self, index: usize) -> Option<Self> {
        if self.width > MIN_WIDTH {
            let width = self.width - 1;
            Some(Partition {
                origin: self.origin + vector_at_index(index, width),
                width: width,
            })
        } else {
            None
        }
    }

    pub fn origin(&self) -> &Point3 {
        &self.origin
    }

    pub fn width(&self) -> RootWidth {
        self.width
    }

    pub fn midpoint(&self) -> Point3 {
        let m = exp(self.width - 1);
        Point3::new(m, m, m)
    }
}

pub trait ComputedCube: ops::Deref<Target = Cube> {
    fn partition(&self) -> &Partition;

    fn depth(&self) -> u8;
}

#[derive(Debug)]
pub enum JoinError {
    LeafJoined,
}

impl fmt::Display for JoinError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for JoinError {
    fn description(&self) -> &str {
        match *self {
            JoinError::LeafJoined => "attempted to join leaf",
        }
    }
}

#[derive(Debug)]
pub enum SubdivideError {
    LimitExceeded,
    BranchSubdivided,
}

impl fmt::Display for SubdivideError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for SubdivideError {
    fn description(&self) -> &str {
        match *self {
            SubdivideError::LimitExceeded => "minimum width limit exceeded",
            SubdivideError::BranchSubdivided => "attempted to subdivide branch",
        }
    }
}

pub trait ComputedCubeMut: ComputedCube + ops::DerefMut {
    fn join(&mut self) -> Result<&mut Self, JoinError> {
        try!(self.deref_mut().join().ok_or(JoinError::LeafJoined));
        Ok(self)
    }

    fn subdivide(&mut self) -> Result<&mut Self, SubdivideError> {
        if self.partition().width() > MIN_WIDTH {
            try!(self.deref_mut().subdivide().ok_or(SubdivideError::BranchSubdivided));
            Ok(self)
        } else {
            Err(SubdivideError::LimitExceeded)
        }
    }
}

#[derive(Clone)]
pub struct Traversal<'a> {
    cube: &'a Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> Traversal<'a> {
    fn new(cube: &'a Cube, root: &'a Partition, partition: Partition) -> Self {
        Traversal {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn iter(&self) -> CubeIter {
        CubeIter::new(self.clone())
    }

    pub fn at_point(&self, point: &Point3, width: RootWidth) -> Self {
        let mut cube = self.cube;
        let mut depth = self.partition.width();

        // Clamp the inputs.
        let point = point.clamp(0, (exp(self.root.width())) - 1);
        let width = exp(width.clamp(MIN_WIDTH, depth));

        while (width >> depth) == 0 {
            match *cube {
                Cube::Branch(ref branch) => {
                    depth = depth - 1;
                    cube = &branch.cubes[index_at_point(&point, depth)]
                }
                _ => break,
            }
        }

        Traversal::new(cube, self.root, Partition::at_point(&point, depth))
    }
}

impl<'a> ComputedCube for Traversal<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> ops::Deref for Traversal<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

pub struct CubeIter<'a> {
    traversals: Vec<Traversal<'a>>,
}

impl<'a> CubeIter<'a> {
    fn new(traversal: Traversal<'a>) -> Self {
        CubeIter { traversals: vec![traversal] }
    }
}

impl<'a> Iterator for CubeIter<'a> {
    type Item = Traversal<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(traversal) = self.traversals.pop() {
            match *traversal.cube {
                Cube::Branch(ref branch) => {
                    for (index, cube) in branch.iter().enumerate() {
                        self.traversals.push(Traversal::new(cube,
                                                            traversal.root,
                                                            traversal.partition()
                                                                .at_index(index)
                                                                .unwrap()));
                    }
                }
                _ => {}
            }
            Some(traversal)
        } else {
            None
        }
    }
}

pub struct TraversalMut<'a> {
    cube: &'a mut Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> TraversalMut<'a> {
    fn new(cube: &'a mut Cube, root: &'a Partition, partition: Partition) -> Self {
        TraversalMut {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn at_point(&'a mut self, point: &Point3, width: RootWidth) -> Self {
        let mut cube: Option<&mut Cube> = Some(self.cube);
        let mut depth = self.partition.width();

        let point = point.clamp(0, (exp(self.root.width())) - 1);
        let width = exp(width.clamp(MIN_WIDTH, depth));

        while (width >> depth) == 0 {
            let inner = cube.take().unwrap();
            match *inner {
                Cube::Branch(ref mut branch) => {
                    depth = depth - 1;
                    cube = Some(&mut branch.cubes[index_at_point(&point, depth)]);
                }
                _ => {
                    cube = Some(inner);
                    break;
                }
            }
        }

        TraversalMut::new(cube.take().unwrap(),
                          self.root,
                          Partition::at_point(&point, depth))
    }
}

impl<'a> ComputedCube for TraversalMut<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> ComputedCubeMut for TraversalMut<'a> {}

impl<'a> ops::Deref for TraversalMut<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

impl<'a> ops::DerefMut for TraversalMut<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.cube
    }
}

pub struct Tree {
    cube: Cube,
    partition: Partition,
}

impl Tree {
    pub fn new(width: RootWidth) -> Self {
        Tree {
            cube: Cube::new(),
            partition: Partition::at_point(&Point3::origin(), width.clamp(MIN_WIDTH, MAX_WIDTH)),
        }
    }

    pub fn iter(&self) -> CubeIter {
        CubeIter::new(self.traverse())
    }

    pub fn traverse(&self) -> Traversal {
        Traversal::new(&self.cube, &self.partition, self.partition.clone())
    }

    pub fn traverse_mut(&mut self) -> TraversalMut {
        TraversalMut::new(&mut self.cube, &self.partition, self.partition.clone())
    }
}

impl ComputedCube for Tree {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        0
    }
}

impl ComputedCubeMut for Tree {}

impl ops::Deref for Tree {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        &self.cube
    }
}

impl ops::DerefMut for Tree {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.cube
    }
}

#[derive(Clone)]
pub enum Cube {
    Leaf(LeafNode),
    Branch(BranchNode),
}

impl Cube {
    fn new() -> Self {
        Cube::Leaf(LeafNode::new())
    }

    fn join(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Branch(branch) => {
                *self = branch.join().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    fn subdivide(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Leaf(leaf) => {
                *self = leaf.subdivide().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    pub fn is_leaf(&self) -> bool {
        match *self {
            Cube::Leaf(_) => true,
            _ => false,
        }
    }
}

impl Default for Cube {
    fn default() -> Self {
        Cube::new()
    }
}

impl From<LeafNode> for Cube {
    fn from(leaf: LeafNode) -> Self {
        Cube::Leaf(leaf)
    }
}

impl From<BranchNode> for Cube {
    fn from(branch: BranchNode) -> Self {
        Cube::Branch(branch)
    }
}

#[derive(Clone, Copy)]
pub struct LeafNode {
    pub geometry: Geometry,
    pub material: ResourceId,
}

impl LeafNode {
    fn new() -> Self {
        LeafNode {
            geometry: Geometry::full(),
            material: 0,
        }
    }

    fn subdivide(self) -> BranchNode {
        // TODO: Transform the geometry of the parent into the children.
        let cube: Cube = self.into();
        BranchNode {
            cubes: Box::new([cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube]),
        }
    }
}

pub struct BranchNode {
    cubes: Box<[Cube; 8]>,
}

impl BranchNode {
    fn join(self) -> LeafNode {
        // TODO: Copy data from one of the original leaves.
        LeafNode::new()
    }
}

impl Clone for BranchNode {
    fn clone(&self) -> Self {
        BranchNode {
            cubes: Box::new([self.cubes[0].clone(),
                             self.cubes[1].clone(),
                             self.cubes[2].clone(),
                             self.cubes[3].clone(),
                             self.cubes[4].clone(),
                             self.cubes[5].clone(),
                             self.cubes[6].clone(),
                             self.cubes[7].clone()]),
        }
    }
}

impl ops::Deref for BranchNode {
    type Target = [Cube];

    fn deref(&self) -> &Self::Target {
        &*self.cubes
    }
}

#[derive(Copy, Clone)]
pub struct Geometry([[Edge; 4]; 3]);

impl Geometry {
    fn full() -> Self {
        Geometry([[Edge::full(); 4]; 3])
    }

    fn empty() -> Self {
        Geometry([[Edge::converged(0); 4]; 3])
    }

    pub fn as_edges_x(&self) -> &[Edge; 4] {
        &self.0[0]
    }
    pub fn as_edges_y(&self) -> &[Edge; 4] {
        &self.0[1]
    }
    pub fn as_edges_z(&self) -> &[Edge; 4] {
        &self.0[2]
    }

    pub fn as_edges_x_mut(&mut self) -> &mut [Edge; 4] {
        &mut self.0[0]
    }
    pub fn as_edges_y_mut(&mut self) -> &mut [Edge; 4] {
        &mut self.0[1]
    }
    pub fn as_edges_z_mut(&mut self) -> &mut [Edge; 4] {
        &mut self.0[2]
    }
}

#[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct Edge(u8);

const MIN_EDGE: u8 = 0;
const MAX_EDGE: u8 = 0x0F;

impl Edge {
    fn full() -> Self {
        Edge(MAX_EDGE)
    }

    fn converged(value: u8) -> Self {
        let value = nalgebra::clamp(value, MIN_EDGE, MAX_EDGE);
        Edge((value << 4) | value)
    }

    pub fn set_front(&mut self, value: u8) {
        let value = nalgebra::clamp(value, MIN_EDGE, self.back());
        self.0 = (value << 4) | self.back();
    }

    pub fn set_back(&mut self, value: u8) {
        let value = nalgebra::clamp(value, self.front(), MAX_EDGE);
        self.0 = (self.front() << 4) | value;
    }

    pub fn front(&self) -> u8 {
        (self.0 & 0xF0) >> 4
    }

    pub fn back(&self) -> u8 {
        self.0 & 0x0F
    }

    pub fn front_transform(&self) -> f32 {
        ((self.front() - MIN_EDGE) as f32) / ((MAX_EDGE - MIN_EDGE) as f32)
    }

    pub fn back_transform(&self) -> f32 {
        let range = MAX_EDGE - MIN_EDGE;
        -((range - (self.back() - MIN_EDGE)) as f32) / (range as f32)
    }
}

trait Subdivision {}

impl Subdivision for [Cube; 8] {}

trait Storage {}

impl Storage for Box<[Cube; 8]> {}

#[cfg_attr(rustfmt, rustfmt_skip)]
fn index_at_point(point: &Point3, width: RootWidth) -> usize {
    ((((point.x >> width) & DiscreteSpace::one()) << 0) |
     (((point.y >> width) & DiscreteSpace::one()) << 1) |
     (((point.z >> width) & DiscreteSpace::one()) << 2)) as usize
}

fn vector_at_index(index: usize, width: RootWidth) -> Vector3 {
    assert!(index < 8);
    let index = index as DiscreteSpace;
    let width = exp(width);
    Vector3::new(((index >> 0) & DiscreteSpace::one()) * width,
                 ((index >> 1) & DiscreteSpace::one()) * width,
                 ((index >> 2) & DiscreteSpace::one()) * width)
}

pub fn exp(width: RootWidth) -> DiscreteSpace {
    if width > 0 {
        DiscreteSpace::one() << (width - 1)
    } else {
        0
    }
}

#[cfg(test)]
mod tests {
    use super::*;
}
<|endoftext|>


<commit_before>// Baseline-Compiler
<commit_msg>base.rs removed<commit_after><|endoftext|>


<commit_before>use std::io::net::ip::SocketAddr;
use std::sync::Future;
use num::BigUint;

/// Trait representing table with known nodes.
///
/// Keeps some reasonable subset of known nodes passed to `update`.
#[unstable]
pub trait GenericNodeTable : Send + Sync {
    /// Store or update node in the table.
    fn update(&mut self, node: &Node) -> bool;
    /// Find given number of node, closest to given ID.
    fn find(&self, id: &BigUint, count: uint) -> Vec<Node>;
}

/// Trait representing RPC implementation.
#[experimental]
pub trait GenericRpc : Send + Sync {
    /// Ping a node, returning true if node seems reachable.
    fn ping(&self, node: &Node) -> Future<bool>;
    /// Find a node with given ID.
    fn find_node(&self, id: &BigUint) -> Future<Node>;
}

/// Structure representing a node in system.
///
/// Every node has an address (IP and port) and a numeric ID, which is
/// used to calculate metrics and look up data.
#[deriving(Clone, Show)]
#[unstable]
pub struct Node {
    pub address: SocketAddr,
    pub id: BigUint
}
<commit_msg>Missed docstrings<commit_after>use std::io::net::ip::SocketAddr;
use std::sync::Future;
use num::BigUint;

/// Trait representing table with known nodes.
///
/// Keeps some reasonable subset of known nodes passed to `update`.
#[unstable]
pub trait GenericNodeTable : Send + Sync {
    /// Store or update node in the table.
    fn update(&mut self, node: &Node) -> bool;
    /// Find given number of node, closest to given ID.
    fn find(&self, id: &BigUint, count: uint) -> Vec<Node>;
}

/// Trait representing RPC implementation.
#[experimental]
pub trait GenericRpc : Send + Sync {
    /// Ping a node, returning true if node seems reachable.
    fn ping(&self, node: &Node) -> Future<bool>;
    /// Find a node with given ID.
    fn find_node(&self, id: &BigUint) -> Future<Node>;
}

/// Structure representing a node in system.
///
/// Every node has an address (IP and port) and a numeric ID, which is
/// used to calculate metrics and look up data.
#[deriving(Clone, Show)]
#[unstable]
pub struct Node {
    /// Network address of the node.
    pub address: SocketAddr,
    /// ID of the node.
    pub id: BigUint
}
<|endoftext|>


<commit_before>#![feature(phase)]

extern crate serialize;
#[phase(plugin, link)]
extern crate hammer;

use std::io::File;
use memory::Memory;
use interpret::interpret;

use hammer::{decode_args, usage};
use std::os;

mod memory;
mod interpret;

#[deriving(Decodable, Show)]
struct BearOpts {
	file: String,
	help: bool
}

hammer_config!(BearOpts "BEAR - Another BF",
	|c| {
		c.short("file", 'f')
    }
)

fn main() {
	let opts: BearOpts = match decode_args(os::args().tail()) {
		Ok(val) => val,
		Err(err) => fail!(err.message)
	};
	if opts.help {
		let (desc, usage_text) = usage::<BearOpts>(true);
	    println!("Usage: {}", os::args().get(0));
	    println!("{}", usage_text);
	    println!("{}", desc.unwrap());
	}
	else {
		let test = match File::open(&Path::new(opts.file)).read_to_end() {
			Ok(val) => {
				match String::from_utf8(val) {
					Ok(val) => val,
					Err(err) => fail!(err)
				}
			},
			Err(err) => fail!(err)
		};

		let mut mem = Memory::new();

		interpret(test, &mut mem);
	}
}<commit_msg>Fix commandline<commit_after>#![feature(phase)]

extern crate serialize;
#[phase(plugin, link)]
extern crate hammer;

use std::io::File;
use memory::Memory;
use interpret::interpret;

use hammer::{decode_args, usage};
use std::os;

mod memory;
mod interpret;

#[deriving(Decodable, Show)]
struct BearOpts {
	file: Option<String>,
	help: bool
}

hammer_config!(BearOpts "BEAR - Another BF",
	|c| {
		c.short("file", 'f')
    }
)

fn main() {
	let opts: BearOpts = match decode_args(os::args().tail()) {
		Ok(val) => val,
		Err(err) => fail!(err.message)
	};
	if opts.help {
		let (desc, usage_text) = usage::<BearOpts>(true);
	    println!("Usage: {}", os::args().get(0));
	    println!("{}", usage_text);
	    println!("{}", desc.unwrap());
	}
	else {
		let filename = match opts.file {
			Some(val) => val,
			None => fail!("--file required")
		};
		let test = match File::open(&Path::new(filename)).read_to_end() {
			Ok(val) => {
				match String::from_utf8(val) {
					Ok(val) => val,
					Err(err) => fail!(err)
				}
			},
			Err(err) => fail!(err.desc)
		};

		let mut mem = Memory::new();

		interpret(test, &mut mem);
	}
}<|endoftext|>


<commit_before>#[macro_use]
extern crate kappa_lisp;
use kappa_lisp::{run_new};
use kappa_lisp::util::*;

#[test]
fn test_funcall(){
    assert_eq!(run_new("(funcall #'+ 1 2)"), Ok(kint(3)));
    assert_eq!(run_new("(funcall #'(lambda (x y) (* x y)) 1 2)"), Ok(kint(2)));
    assert_eq!(run_new("(funcall (lambda (x y) (* x y)) 1 2)"), Ok(kint(2)))
}

#[test]
fn test_add(){
    assert_eq!(run_new("(+)"), Ok(kint(0)));
    assert_eq!(run_new("(+ 1)"), Ok(kint(1)));
    assert_eq!(run_new("(+ 1 2)"), Ok(kint(3)));
    assert_eq!(run_new("(+ 1 2 3)"), Ok(kint(6)));
    assert_eq!(run_new("(+ 1 2 3.0)"), Ok(kfloat(6.0)));
}

#[test]
fn test_sub(){
    assert_eq!(run_new("(-)"), Ok(kint(0)));
    assert_eq!(run_new("(- 1)"), Ok(kint(-1)));
    assert_eq!(run_new("(- 1 2)"), Ok(kint(-1)));
    assert_eq!(run_new("(- 1.0 2 3)"), Ok(kfloat(-4.0)));
}

#[test]
fn test_mul(){
    assert_eq!(run_new("(*)"), Ok(kint(1)));
    assert_eq!(run_new("(* 1)"), Ok(kint(1)));
    assert_eq!(run_new("(* 1 2.0)"), Ok(kfloat(2.0)));
    assert_eq!(run_new("(* 1 2 3)"), Ok(kint(6)));
}

#[test]
fn test_div(){
    assert_eq!(run_new("(/)"), Ok(kint(1)));
    assert_eq!(run_new("(/ 1)"), Ok(kint(1)));
    assert_eq!(run_new("(/ 3 2)"), Ok(kint(1)));
    assert_eq!(run_new("(/ 3 2.0)"), Ok(kfloat(1.5)));
    assert_eq!(run_new("(/ 3 2 1)"), Ok(kint(1)));
}

#[test]
fn test_nested_arith(){
    assert_eq!(run_new("(/ (- (+ 1 (* 2 3)) 3) 2)"), Ok(kint(2)));
}

#[test]
fn test_concat(){
    assert_eq!(run_new("(concat \"a\" \"b\" \"cd\")"), Ok(kstr("abcd")))
}

#[test]
fn test_cons() {
    assert_eq!(run_new("(cons 1 2)"), Ok(kcons(kint(1), kint(2))));
    assert_eq!(run_new("(cons () 2)"), Ok(kcons(knil(), kint(2))));
}

#[test]
fn test_car() {
    assert_eq!(run_new("(car (cons 1 2))"), Ok(kint(1)));
    assert_eq!(run_new("(car (list 1 2))"), Ok(kint(1)));
}

#[test]
fn test_cdr() {
    assert_eq!(run_new("(cdr (cons 1 2))"), Ok(kint(2)));
    assert_eq!(run_new("(cdr (list 1 2))"), Ok(klist!(kint(2))));
}

#[test]
fn test_list() {
    assert_eq!(run_new("(list)"), Ok(knil()));
    assert_eq!(run_new("(list 1)"), Ok(klist!(kint(1))));
    assert_eq!(run_new("(list 1 2)"), Ok(klist!(kint(1), kint(2))));
}

#[test]
fn test_equal_p() {
    assert_eq!(run_new("(equal? 1 1)"), Ok(kint(1)));
    assert_eq!(run_new("(equal? 'sym 'sym)"), Ok(kint(1)));
    assert_eq!(run_new("(equal? \"str\" \"str\")"), Ok(kint(1)));
    assert_eq!(run_new("(equal? 1 \"str\")"), Ok(knil()));
    assert_eq!(run_new("(equal? 'sym \"str\")"), Ok(knil()));
    assert_eq!(run_new("(equal? (list \"str\") \"str\")"), Ok(knil()));
}

#[test]
fn test_string_to_number() {
    assert_eq!(run_new("(string-to-number \"1\")"), Ok(kint(1)));
}

#[test]
fn test_substring() {
    assert_eq!(run_new("(substring \"abcdefg\" 0 3)"), Ok(kstr("abc")));
    assert_eq!(run_new("(substring \"abcdefg\" 4 6)"), Ok(kstr("ef")));
}

#[test]
fn test_t() {
    assert_eq!(run_new("t"), Ok(ksym("t")))
}
<commit_msg>use t in test too<commit_after>#[macro_use]
extern crate kappa_lisp;
use kappa_lisp::{run_new};
use kappa_lisp::util::*;

#[test]
fn test_funcall(){
    assert_eq!(run_new("(funcall #'+ 1 2)"), Ok(kint(3)));
    assert_eq!(run_new("(funcall #'(lambda (x y) (* x y)) 1 2)"), Ok(kint(2)));
    assert_eq!(run_new("(funcall (lambda (x y) (* x y)) 1 2)"), Ok(kint(2)))
}

#[test]
fn test_add(){
    assert_eq!(run_new("(+)"), Ok(kint(0)));
    assert_eq!(run_new("(+ 1)"), Ok(kint(1)));
    assert_eq!(run_new("(+ 1 2)"), Ok(kint(3)));
    assert_eq!(run_new("(+ 1 2 3)"), Ok(kint(6)));
    assert_eq!(run_new("(+ 1 2 3.0)"), Ok(kfloat(6.0)));
}

#[test]
fn test_sub(){
    assert_eq!(run_new("(-)"), Ok(kint(0)));
    assert_eq!(run_new("(- 1)"), Ok(kint(-1)));
    assert_eq!(run_new("(- 1 2)"), Ok(kint(-1)));
    assert_eq!(run_new("(- 1.0 2 3)"), Ok(kfloat(-4.0)));
}

#[test]
fn test_mul(){
    assert_eq!(run_new("(*)"), Ok(kint(1)));
    assert_eq!(run_new("(* 1)"), Ok(kint(1)));
    assert_eq!(run_new("(* 1 2.0)"), Ok(kfloat(2.0)));
    assert_eq!(run_new("(* 1 2 3)"), Ok(kint(6)));
}

#[test]
fn test_div(){
    assert_eq!(run_new("(/)"), Ok(kint(1)));
    assert_eq!(run_new("(/ 1)"), Ok(kint(1)));
    assert_eq!(run_new("(/ 3 2)"), Ok(kint(1)));
    assert_eq!(run_new("(/ 3 2.0)"), Ok(kfloat(1.5)));
    assert_eq!(run_new("(/ 3 2 1)"), Ok(kint(1)));
}

#[test]
fn test_nested_arith(){
    assert_eq!(run_new("(/ (- (+ 1 (* 2 3)) 3) 2)"), Ok(kint(2)));
}

#[test]
fn test_concat(){
    assert_eq!(run_new("(concat \"a\" \"b\" \"cd\")"), Ok(kstr("abcd")))
}

#[test]
fn test_cons() {
    assert_eq!(run_new("(cons 1 2)"), Ok(kcons(kint(1), kint(2))));
    assert_eq!(run_new("(cons () 2)"), Ok(kcons(knil(), kint(2))));
}

#[test]
fn test_car() {
    assert_eq!(run_new("(car (cons 1 2))"), Ok(kint(1)));
    assert_eq!(run_new("(car (list 1 2))"), Ok(kint(1)));
}

#[test]
fn test_cdr() {
    assert_eq!(run_new("(cdr (cons 1 2))"), Ok(kint(2)));
    assert_eq!(run_new("(cdr (list 1 2))"), Ok(klist!(kint(2))));
}

#[test]
fn test_list() {
    assert_eq!(run_new("(list)"), Ok(knil()));
    assert_eq!(run_new("(list 1)"), Ok(klist!(kint(1))));
    assert_eq!(run_new("(list 1 2)"), Ok(klist!(kint(1), kint(2))));
}

#[test]
fn test_equal_p() {
    assert_eq!(run_new("(equal? 1 1)"), Ok(ksym("t")));
    assert_eq!(run_new("(equal? 'sym 'sym)"), Ok(ksym("t")));
    assert_eq!(run_new("(equal? \"str\" \"str\")"), Ok(ksym("t")));
    assert_eq!(run_new("(equal? 1 \"str\")"), Ok(knil()));
    assert_eq!(run_new("(equal? 'sym \"str\")"), Ok(knil()));
    assert_eq!(run_new("(equal? (list \"str\") \"str\")"), Ok(knil()));
}

#[test]
fn test_string_to_number() {
    assert_eq!(run_new("(string-to-number \"1\")"), Ok(kint(1)));
}

#[test]
fn test_substring() {
    assert_eq!(run_new("(substring \"abcdefg\" 0 3)"), Ok(kstr("abc")));
    assert_eq!(run_new("(substring \"abcdefg\" 4 6)"), Ok(kstr("ef")));
}

#[test]
fn test_t() {
    assert_eq!(run_new("t"), Ok(ksym("t")))
}
<|endoftext|>


<commit_before>use std::ffi::{OsString, OsStr};

use ops::{self, Compilation};
use util::{self, CargoResult, CargoTestError, ProcessError};
use core::Workspace;

pub struct TestOptions<'a> {
    pub compile_opts: ops::CompileOptions<'a>,
    pub no_run: bool,
    pub no_fail_fast: bool,
    pub only_doc: bool,
}

pub fn run_tests(ws: &Workspace,
                 options: &TestOptions,
                 test_args: &[String]) -> CargoResult<Option<CargoTestError>> {
    let compilation = compile_tests(ws, options)?;

    if options.no_run {
        return Ok(None)
    }
    let mut errors = if options.only_doc {
        run_doc_tests(options, test_args, &compilation)?
    } else {
        run_unit_tests(options, test_args, &compilation)?
    };

    // If we have an error and want to fail fast, return
    if !errors.is_empty() && !options.no_fail_fast {
        return Ok(Some(CargoTestError::new(errors)))
    }

    // If a specific test was requested or we're not running any tests at all,
    // don't run any doc tests.
    if let ops::CompileFilter::Only { .. } = options.compile_opts.filter {
        match errors.len() {
            0 => return Ok(None),
            _ => return Ok(Some(CargoTestError::new(errors)))
        }
    }

    errors.extend(run_doc_tests(options, test_args, &compilation)?);
    if errors.is_empty() {
        Ok(None)
    } else {
        Ok(Some(CargoTestError::new(errors)))
    }
}

pub fn run_benches(ws: &Workspace,
                   options: &TestOptions,
                   args: &[String]) -> CargoResult<Option<CargoTestError>> {
    let mut args = args.to_vec();
    args.push("--bench".to_string());
    let compilation = compile_tests(ws, options)?;

    if options.no_run {
        return Ok(None)
    }
    let errors = run_unit_tests(options, &args, &compilation)?;
    match errors.len() {
        0 => Ok(None),
        _ => Ok(Some(CargoTestError::new(errors))),
    }
}

fn compile_tests<'a>(ws: &Workspace<'a>,
                     options: &TestOptions<'a>)
                     -> CargoResult<Compilation<'a>> {
    let mut compilation = ops::compile(ws, &options.compile_opts)?;
    compilation.tests.sort_by(|a, b| {
        (a.0.package_id(), &a.1).cmp(&(b.0.package_id(), &b.1))
    });
    Ok(compilation)
}

/// Run the unit and integration tests of a project.
fn run_unit_tests(options: &TestOptions,
                  test_args: &[String],
                  compilation: &Compilation)
                  -> CargoResult<Vec<ProcessError>> {
    let config = options.compile_opts.config;
    let cwd = options.compile_opts.config.cwd();

    let mut errors = Vec::new();

    for &(ref pkg, _, ref exe) in &compilation.tests {
        let to_display = match util::without_prefix(exe, &cwd) {
            Some(path) => path,
            None => &**exe,
        };
        let mut cmd = compilation.target_process(exe, pkg)?;
        cmd.args(test_args);
        config.shell().concise(|shell| {
            shell.status("Running", to_display.display().to_string())
        })?;
        config.shell().verbose(|shell| {
            shell.status("Running", cmd.to_string())
        })?;

        if let Err(e) = cmd.exec() {
            errors.push(e);
            if !options.no_fail_fast {
                break
            }
        }
    }
    Ok(errors)
}

fn run_doc_tests(options: &TestOptions,
                 test_args: &[String],
                 compilation: &Compilation)
                 -> CargoResult<Vec<ProcessError>> {
    let mut errors = Vec::new();
    let config = options.compile_opts.config;

    // We don't build/rust doctests if target != host
    if config.rustc()?.host != compilation.target {
        return Ok(errors);
    }

    let libs = compilation.to_doc_test.iter().map(|package| {
        (package, package.targets().iter().filter(|t| t.doctested())
                         .map(|t| (t.src_path(), t.name(), t.crate_name())))
    });

    for (package, tests) in libs {
        for (lib, name, crate_name) in tests {
            config.shell().status("Doc-tests", name)?;
            let mut p = compilation.rustdoc_process(package)?;
            p.arg("--test").arg(lib)
             .arg("--crate-name").arg(&crate_name);

            for &rust_dep in &[&compilation.deps_output] {
                let mut arg = OsString::from("dependency=");
                arg.push(rust_dep);
                p.arg("-L").arg(arg);
            }
            for native_dep in compilation.native_dirs.iter() {
                p.arg("-L").arg(native_dep);
            }

            if test_args.len() > 0 {
                p.arg("--test-args").arg(&test_args.join(" "));
            }

            if let Some(cfgs) = compilation.cfgs.get(&package.package_id()) {
                for cfg in cfgs.iter() {
                    p.arg("--cfg").arg(cfg);
                }
            }

            for (_, libs) in compilation.libraries.iter() {
                for &(ref target, ref lib) in libs.iter() {
                    // Note that we can *only* doctest rlib outputs here.  A
                    // staticlib output cannot be linked by the compiler (it just
                    // doesn't do that). A dylib output, however, can be linked by
                    // the compiler, but will always fail. Currently all dylibs are
                    // built as "static dylibs" where the standard library is
                    // statically linked into the dylib. The doc tests fail,
                    // however, for now as they try to link the standard library
                    // dynamically as well, causing problems. As a result we only
                    // pass `--extern` for rlib deps and skip out on all other
                    // artifacts.
                    if lib.extension() != Some(OsStr::new("rlib")) &&
                       !target.for_host() {
                        continue
                    }
                    let mut arg = OsString::from(target.crate_name());
                    arg.push("=");
                    arg.push(lib);
                    p.arg("--extern").arg(&arg);
                }
            }

            config.shell().verbose(|shell| {
                shell.status("Running", p.to_string())
            })?;
            if let Err(e) = p.exec() {
                errors.push(e);
                if !options.no_fail_fast {
                    return Ok(errors);
                }
            }
        }
    }
    Ok(errors)
}
<commit_msg>Pass multiples --test-args to the tester<commit_after>use std::ffi::{OsString, OsStr};

use ops::{self, Compilation};
use util::{self, CargoResult, CargoTestError, ProcessError};
use core::Workspace;

pub struct TestOptions<'a> {
    pub compile_opts: ops::CompileOptions<'a>,
    pub no_run: bool,
    pub no_fail_fast: bool,
    pub only_doc: bool,
}

pub fn run_tests(ws: &Workspace,
                 options: &TestOptions,
                 test_args: &[String]) -> CargoResult<Option<CargoTestError>> {
    let compilation = compile_tests(ws, options)?;

    if options.no_run {
        return Ok(None)
    }
    let mut errors = if options.only_doc {
        run_doc_tests(options, test_args, &compilation)?
    } else {
        run_unit_tests(options, test_args, &compilation)?
    };

    // If we have an error and want to fail fast, return
    if !errors.is_empty() && !options.no_fail_fast {
        return Ok(Some(CargoTestError::new(errors)))
    }

    // If a specific test was requested or we're not running any tests at all,
    // don't run any doc tests.
    if let ops::CompileFilter::Only { .. } = options.compile_opts.filter {
        match errors.len() {
            0 => return Ok(None),
            _ => return Ok(Some(CargoTestError::new(errors)))
        }
    }

    errors.extend(run_doc_tests(options, test_args, &compilation)?);
    if errors.is_empty() {
        Ok(None)
    } else {
        Ok(Some(CargoTestError::new(errors)))
    }
}

pub fn run_benches(ws: &Workspace,
                   options: &TestOptions,
                   args: &[String]) -> CargoResult<Option<CargoTestError>> {
    let mut args = args.to_vec();
    args.push("--bench".to_string());
    let compilation = compile_tests(ws, options)?;

    if options.no_run {
        return Ok(None)
    }
    let errors = run_unit_tests(options, &args, &compilation)?;
    match errors.len() {
        0 => Ok(None),
        _ => Ok(Some(CargoTestError::new(errors))),
    }
}

fn compile_tests<'a>(ws: &Workspace<'a>,
                     options: &TestOptions<'a>)
                     -> CargoResult<Compilation<'a>> {
    let mut compilation = ops::compile(ws, &options.compile_opts)?;
    compilation.tests.sort_by(|a, b| {
        (a.0.package_id(), &a.1).cmp(&(b.0.package_id(), &b.1))
    });
    Ok(compilation)
}

/// Run the unit and integration tests of a project.
fn run_unit_tests(options: &TestOptions,
                  test_args: &[String],
                  compilation: &Compilation)
                  -> CargoResult<Vec<ProcessError>> {
    let config = options.compile_opts.config;
    let cwd = options.compile_opts.config.cwd();

    let mut errors = Vec::new();

    for &(ref pkg, _, ref exe) in &compilation.tests {
        let to_display = match util::without_prefix(exe, &cwd) {
            Some(path) => path,
            None => &**exe,
        };
        let mut cmd = compilation.target_process(exe, pkg)?;
        cmd.args(test_args);
        config.shell().concise(|shell| {
            shell.status("Running", to_display.display().to_string())
        })?;
        config.shell().verbose(|shell| {
            shell.status("Running", cmd.to_string())
        })?;

        if let Err(e) = cmd.exec() {
            errors.push(e);
            if !options.no_fail_fast {
                break
            }
        }
    }
    Ok(errors)
}

fn run_doc_tests(options: &TestOptions,
                 test_args: &[String],
                 compilation: &Compilation)
                 -> CargoResult<Vec<ProcessError>> {
    let mut errors = Vec::new();
    let config = options.compile_opts.config;

    // We don't build/rust doctests if target != host
    if config.rustc()?.host != compilation.target {
        return Ok(errors);
    }

    let libs = compilation.to_doc_test.iter().map(|package| {
        (package, package.targets().iter().filter(|t| t.doctested())
                         .map(|t| (t.src_path(), t.name(), t.crate_name())))
    });

    for (package, tests) in libs {
        for (lib, name, crate_name) in tests {
            config.shell().status("Doc-tests", name)?;
            let mut p = compilation.rustdoc_process(package)?;
            p.arg("--test").arg(lib)
             .arg("--crate-name").arg(&crate_name);

            for &rust_dep in &[&compilation.deps_output] {
                let mut arg = OsString::from("dependency=");
                arg.push(rust_dep);
                p.arg("-L").arg(arg);
            }
            for native_dep in compilation.native_dirs.iter() {
                p.arg("-L").arg(native_dep);
            }

            for arg in test_args {
                p.arg("--test-args").arg(arg);
            }

            if let Some(cfgs) = compilation.cfgs.get(&package.package_id()) {
                for cfg in cfgs.iter() {
                    p.arg("--cfg").arg(cfg);
                }
            }

            for (_, libs) in compilation.libraries.iter() {
                for &(ref target, ref lib) in libs.iter() {
                    // Note that we can *only* doctest rlib outputs here.  A
                    // staticlib output cannot be linked by the compiler (it just
                    // doesn't do that). A dylib output, however, can be linked by
                    // the compiler, but will always fail. Currently all dylibs are
                    // built as "static dylibs" where the standard library is
                    // statically linked into the dylib. The doc tests fail,
                    // however, for now as they try to link the standard library
                    // dynamically as well, causing problems. As a result we only
                    // pass `--extern` for rlib deps and skip out on all other
                    // artifacts.
                    if lib.extension() != Some(OsStr::new("rlib")) &&
                       !target.for_host() {
                        continue
                    }
                    let mut arg = OsString::from(target.crate_name());
                    arg.push("=");
                    arg.push(lib);
                    p.arg("--extern").arg(&arg);
                }
            }

            config.shell().verbose(|shell| {
                shell.status("Running", p.to_string())
            })?;
            if let Err(e) = p.exec() {
                errors.push(e);
                if !options.no_fail_fast {
                    return Ok(errors);
                }
            }
        }
    }
    Ok(errors)
}
<|endoftext|>


<commit_before>use prelude::*;
use rustc::mir::interpret::{GlobalId, AllocId, read_target_uint};
use rustc_mir::interpret::{CompileTimeEvaluator, Memory, MemoryKind};
use cranelift_module::*;

pub fn trans_constant<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, const_: &Constant<'tcx>) -> CValue<'tcx> {
    let value = match const_.literal {
        Literal::Value { value } => value,
        Literal::Promoted { index } => fx
            .tcx
            .const_eval(ParamEnv::reveal_all().and(GlobalId {
                instance: fx.instance,
                promoted: Some(index),
            }))
            .unwrap(),
    };

    let layout = fx.layout_of(const_.ty);
    match const_.ty.sty {
        TypeVariants::TyBool => {
            let bits = value.to_scalar().unwrap().to_bits(layout.size).unwrap();
            CValue::const_val(fx, const_.ty, bits as u64 as i64)
        }
        TypeVariants::TyUint(_) => {
            let bits = value.to_scalar().unwrap().to_bits(layout.size).unwrap();
            CValue::const_val(fx, const_.ty, bits as u64 as i64)
        }
        TypeVariants::TyInt(_) => {
            let bits = value.to_scalar().unwrap().to_bits(layout.size).unwrap();
            CValue::const_val(fx, const_.ty, bits as i128 as i64)
        }
        TypeVariants::TyFnDef(def_id, substs) => {
            let func_ref = fx.get_function_ref(Instance::new(def_id, substs));
            CValue::Func(func_ref, fx.layout_of(const_.ty))
        }
        _ => {
            let mut memory = Memory::<CompileTimeEvaluator>::new(fx.tcx.at(DUMMY_SP), ());
            let alloc = fx.tcx.const_value_to_allocation(value);
            //println!("const value: {:?} allocation: {:?}", value, alloc);
            let alloc_id = memory.allocate_value(alloc.clone(), MemoryKind::Stack).unwrap();
            let data_id = get_global_for_alloc_id(fx, &memory, alloc_id);
            let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
            // TODO: does global_value return a ptr of a val?
            let global_ptr = fx.bcx.ins().global_value(types::I64, local_data_id);
            CValue::ByRef(global_ptr, layout)
        }
    }
}

// If ret.1 is true, then the global didn't exist before
fn define_global_for_alloc_id(fx: &mut FunctionCx, alloc_id: AllocId, todo: &mut HashMap<AllocId, DataId>) -> (DataId, bool) {
    use std::collections::hash_map::Entry;
    match fx.constants.entry(alloc_id) {
        Entry::Occupied(mut occ) => {
            (*occ.get_mut(), false)
        }
        Entry::Vacant(vac) => {
            let data_id = fx.module.declare_data(&alloc_id.0.to_string(), Linkage::Local, false).unwrap();
            todo.insert(alloc_id, data_id);
            vac.insert(data_id);
            (data_id, true)
        }
    }
}

fn get_global_for_alloc_id(fx: &mut FunctionCx, memory: &Memory<CompileTimeEvaluator>, alloc_id: AllocId) -> DataId {
    if let Some(data_id) = fx.constants.get(&alloc_id) {
        return *data_id;
    }

    let mut todo = HashMap::new();
    let mut done = HashSet::new();
    define_global_for_alloc_id(fx, alloc_id, &mut todo);

    while let Some((alloc_id, data_id)) = { let next = todo.drain().next(); next } {
        println!("cur: {:?}:{:?} todo: {:?} done: {:?}", alloc_id, data_id, todo, done);

        let alloc = memory.get(alloc_id).unwrap();
        let mut data_ctx = DataContext::new();

        data_ctx.define(alloc.bytes.to_vec().into_boxed_slice(), Writability::Readonly);

        for &(offset, reloc) in alloc.relocations.iter() {
            let data_id = define_global_for_alloc_id(fx, reloc, &mut todo).0;

            let reloc_offset = {
                let endianness = memory.endianness();
                let offset = offset.bytes() as usize;
                let ptr_size = fx.tcx.data_layout.pointer_size;
                let bytes = &alloc.bytes[offset..offset + ptr_size.bytes() as usize];
                read_target_uint(endianness, bytes).unwrap()
            };

            // TODO: is this a correct usage of the api
            let global_value = fx.module.declare_data_in_data(data_id, &mut data_ctx);
            data_ctx.write_data_addr(reloc_offset as u32, global_value, 0);
        }

        fx.module.define_data(data_id, &data_ctx).unwrap();
        done.insert(data_id);
    }
    for data_id in done.drain() {
        fx.module.finalize_data(data_id);
    }
    *fx.constants.get(&alloc_id).unwrap()
}
<commit_msg>Monomorphize type of constant<commit_after>use prelude::*;
use rustc::mir::interpret::{GlobalId, AllocId, read_target_uint};
use rustc_mir::interpret::{CompileTimeEvaluator, Memory, MemoryKind};
use cranelift_module::*;

pub fn trans_constant<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, const_: &Constant<'tcx>) -> CValue<'tcx> {
    let value = match const_.literal {
        Literal::Value { value } => value,
        Literal::Promoted { index } => fx
            .tcx
            .const_eval(ParamEnv::reveal_all().and(GlobalId {
                instance: fx.instance,
                promoted: Some(index),
            }))
            .unwrap(),
    };

    let ty = fx.monomorphize(&const_.ty);
    let layout = fx.layout_of(ty);
    match ty.sty {
        TypeVariants::TyBool => {
            let bits = value.to_scalar().unwrap().to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as u64 as i64)
        }
        TypeVariants::TyUint(_) => {
            let bits = value.to_scalar().unwrap().to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as u64 as i64)
        }
        TypeVariants::TyInt(_) => {
            let bits = value.to_scalar().unwrap().to_bits(layout.size).unwrap();
            CValue::const_val(fx, ty, bits as i128 as i64)
        }
        TypeVariants::TyFnDef(def_id, substs) => {
            let func_ref = fx.get_function_ref(Instance::new(def_id, substs));
            CValue::Func(func_ref, layout)
        }
        _ => {
            let mut memory = Memory::<CompileTimeEvaluator>::new(fx.tcx.at(DUMMY_SP), ());
            let alloc = fx.tcx.const_value_to_allocation(value);
            //println!("const value: {:?} allocation: {:?}", value, alloc);
            let alloc_id = memory.allocate_value(alloc.clone(), MemoryKind::Stack).unwrap();
            let data_id = get_global_for_alloc_id(fx, &memory, alloc_id);
            let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
            // TODO: does global_value return a ptr of a val?
            let global_ptr = fx.bcx.ins().global_value(types::I64, local_data_id);
            CValue::ByRef(global_ptr, layout)
        }
    }
}

// If ret.1 is true, then the global didn't exist before
fn define_global_for_alloc_id(fx: &mut FunctionCx, alloc_id: AllocId, todo: &mut HashMap<AllocId, DataId>) -> (DataId, bool) {
    use std::collections::hash_map::Entry;
    match fx.constants.entry(alloc_id) {
        Entry::Occupied(mut occ) => {
            (*occ.get_mut(), false)
        }
        Entry::Vacant(vac) => {
            let data_id = fx.module.declare_data(&alloc_id.0.to_string(), Linkage::Local, false).unwrap();
            todo.insert(alloc_id, data_id);
            vac.insert(data_id);
            (data_id, true)
        }
    }
}

fn get_global_for_alloc_id(fx: &mut FunctionCx, memory: &Memory<CompileTimeEvaluator>, alloc_id: AllocId) -> DataId {
    if let Some(data_id) = fx.constants.get(&alloc_id) {
        return *data_id;
    }

    let mut todo = HashMap::new();
    let mut done = HashSet::new();
    define_global_for_alloc_id(fx, alloc_id, &mut todo);

    while let Some((alloc_id, data_id)) = { let next = todo.drain().next(); next } {
        println!("cur: {:?}:{:?} todo: {:?} done: {:?}", alloc_id, data_id, todo, done);

        let alloc = memory.get(alloc_id).unwrap();
        let mut data_ctx = DataContext::new();

        data_ctx.define(alloc.bytes.to_vec().into_boxed_slice(), Writability::Readonly);

        for &(offset, reloc) in alloc.relocations.iter() {
            let data_id = define_global_for_alloc_id(fx, reloc, &mut todo).0;

            let reloc_offset = {
                let endianness = memory.endianness();
                let offset = offset.bytes() as usize;
                let ptr_size = fx.tcx.data_layout.pointer_size;
                let bytes = &alloc.bytes[offset..offset + ptr_size.bytes() as usize];
                read_target_uint(endianness, bytes).unwrap()
            };

            // TODO: is this a correct usage of the api
            let global_value = fx.module.declare_data_in_data(data_id, &mut data_ctx);
            data_ctx.write_data_addr(reloc_offset as u32, global_value, 0);
        }

        fx.module.define_data(data_id, &data_ctx).unwrap();
        done.insert(data_id);
    }
    for data_id in done.drain() {
        fx.module.finalize_data(data_id);
    }
    *fx.constants.get(&alloc_id).unwrap()
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, All Contributors (see CONTRIBUTORS file)
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

extern crate pumpkindb;

extern crate config;
extern crate nom;
extern crate rustyline;
extern crate ansi_term;
extern crate uuid;

use pumpkindb::script;
use pumpkindb::script::compose::*;
use pumpkindb::script::compose::Item::*;

extern crate byteorder;

use std::io::prelude::*;
use std::net::TcpStream;

use byteorder::{ByteOrder, BigEndian};

use rustyline::error::ReadlineError;
use rustyline::Editor;
use rustyline::history::History;

use std::fmt::Write;
use std::io::Write as IoWrite;

use ansi_term::Colour::Red;

use std::str;

use uuid::Uuid;

fn main() {
    let _ = config::merge(config::Environment::new("pumpkindb"));
    let _ = config::set_default("prompt", "PumpkinDB> ");
    let formatted_prompt = format!("{}", config::get_str("prompt").unwrap());
    let mut current_prompt = formatted_prompt.as_str();

    let mut stream = TcpStream::connect("0.0.0.0:9981").unwrap();

    let mut rl = Editor::<()>::new();
    let mut r = Vec::new();

    let mut multine = History::new();
    println!("Connected to PumpkinDB at 0.0.0.0:9981");
    println!("Type ?h for help.");
    loop {
        match rl.readline(current_prompt) {
            Ok(text) => {
                let mut program = String::new();
                let text_str = text.as_str();
                let text_bytes = text_str.as_bytes();
                if text_bytes.len() >= 2 && text_bytes[0] == 63u8 {
                    if text_bytes[1] == 104u8 {
                        println!("\nTo end a statement, type `.`.");
                        println!("To quit, hit ^C");
                        println!("Further help online at http://pumpkindb.org/doc/");
                        println!("Missing a feature? Let us know at https://github.com/PumpkinDB/PumpkinDB/issues/\n");
                    }
                } else if text_bytes[text_str.len() - 1] == 46u8 {
                    let rest = str::from_utf8(&text.as_bytes()[..text_str.len() - 1]).unwrap();
                    multine.add(&rest);
                    for i in 0..multine.len() {
                        program.push_str(multine.get(i).unwrap().as_str());
                    }
                    multine.clear();
                    current_prompt = formatted_prompt.as_str();
                } else {
                    multine.add(&text);
                    multine.add(&" ");
                    current_prompt = "..> ";
                }
                if program.len() > 0 {
                    rl.add_history_entry(&program);
                    match script::parse(&program) {
                        Ok(compiled) => {
                            let uuid = Uuid::new_v4();
                            let msg : Vec<u8> = Program(vec![
                                Data(&compiled), Word("TRY"),
                                Data(uuid.as_bytes()), WordRef("topic"), Word("SET"),
                                Word("topic"),
                                Word("SUBSCRIBE"), Word("STACK"), Word("topic"), Word("SEND"),
                                Word("topic"), Word("UNSUBSCRIBE")
                            ]).into();
                            let mut buf = [0u8; 4];

                            BigEndian::write_u32(&mut buf, msg.len() as u32);
                            stream.write_all(buf.as_ref()).unwrap();
                            stream.write_all(msg.as_ref()).unwrap();

                            stream.read(&mut buf).unwrap();

                            let msg_len = BigEndian::read_u32(&mut buf);

                            let s_ref = <TcpStream as Read>::by_ref(&mut stream);

                            r.clear();

                            match s_ref.take(msg_len as u64).read_to_end(&mut r) {
                                Ok(0) => {
                                },
                                Ok(_) => {
                                    let mut input = r.clone();
                                    let mut top_level = true;
                                    let mut s = String::new();
                                    while input.len()> 0 {
                                        match script::binparser::data(input.clone().as_slice()) {
                                            nom::IResult::Done(rest, data) => {
                                                let (_, size) = script::binparser::data_size(data).unwrap();
                                                let data = &data[script::offset_by_size(size)..];

                                                input = Vec::from(rest);

                                                if rest.len() == 0 && top_level {
                                                    top_level = false;
                                                    if data.len() > 0 {
                                                        let _ = write!(&mut s, "{}", Red.paint("Error: "));
                                                        input = Vec::from(data);
                                                    }
                                                } else {
                                                    if data.iter().all(|c| *c >= 0x20 && *c <= 0x7e) {
                                                        let _ = write!(&mut s, "{:?} ", str::from_utf8(data).unwrap());
                                                    } else {
                                                        let _ = write!(&mut s, "0x");
                                                        for b in Vec::from(data) {
                                                            let _ = write!(&mut s, "{:02x}", b);
                                                        }
                                                        let _ = write!(&mut s, " ");
                                                    }
                                                }
                                            },
                                            e => {
                                                panic!("{:?}", e);
                                            }
                                        }
                                    }
                                    println!("{}", s);
                                },
                                Err(e) => {
                                    panic!("{}", e);
                                }
                            }
                        },
                        Err(err) => {
                            println!("Script error: {:?}", err);
                        }
                    }
                }
            }
            Err(ReadlineError::Interrupted) => {
                println!("Aborted");
                break
            },
            Err(ReadlineError::Eof) => {
                println!("Exiting");
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }

    }
}<commit_msg>Problem: `?` is allowed it words.<commit_after>// Copyright (c) 2017, All Contributors (see CONTRIBUTORS file)
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

extern crate pumpkindb;

extern crate config;
extern crate nom;
extern crate rustyline;
extern crate ansi_term;
extern crate uuid;

use pumpkindb::script;
use pumpkindb::script::compose::*;
use pumpkindb::script::compose::Item::*;

extern crate byteorder;

use std::io::prelude::*;
use std::net::TcpStream;

use byteorder::{ByteOrder, BigEndian};

use rustyline::error::ReadlineError;
use rustyline::Editor;
use rustyline::history::History;

use std::fmt::Write;
use std::io::Write as IoWrite;

use ansi_term::Colour::Red;

use std::str;

use uuid::Uuid;

fn main() {
    let _ = config::merge(config::Environment::new("pumpkindb"));
    let _ = config::set_default("prompt", "PumpkinDB> ");
    let formatted_prompt = format!("{}", config::get_str("prompt").unwrap());
    let mut current_prompt = formatted_prompt.as_str();

    let mut stream = TcpStream::connect("0.0.0.0:9981").unwrap();

    let mut rl = Editor::<()>::new();
    let mut r = Vec::new();

    let mut multine = History::new();
    println!("Connected to PumpkinDB at 0.0.0.0:9981");
    println!("Type \\h for help.");
    loop {
        match rl.readline(current_prompt) {
            Ok(text) => {
                let mut program = String::new();
                let text_str = text.as_str();
                let text_bytes = text_str.as_bytes();
                if text_bytes.len() >= 2 && text_bytes[0] == 92u8 {
                    if text_bytes[1] == 104u8 {
                        println!("\nTo end a statement, type `.`.");
                        println!("To quit, hit ^C");
                        println!("Further help online at http://pumpkindb.org/doc/");
                        println!("Missing a feature? Let us know at https://github.com/PumpkinDB/PumpkinDB/issues/\n");
                    }
                } else if text_bytes[text_str.len() - 1] == 46u8 {
                    let rest = str::from_utf8(&text.as_bytes()[..text_str.len() - 1]).unwrap();
                    multine.add(&rest);
                    for i in 0..multine.len() {
                        program.push_str(multine.get(i).unwrap().as_str());
                    }
                    multine.clear();
                    current_prompt = formatted_prompt.as_str();
                } else {
                    multine.add(&text);
                    multine.add(&" ");
                    current_prompt = "..> ";
                }
                if program.len() > 0 {
                    rl.add_history_entry(&program);
                    match script::parse(&program) {
                        Ok(compiled) => {
                            let uuid = Uuid::new_v4();
                            let msg : Vec<u8> = Program(vec![
                                Data(&compiled), Word("TRY"),
                                Data(uuid.as_bytes()), WordRef("topic"), Word("SET"),
                                Word("topic"),
                                Word("SUBSCRIBE"), Word("STACK"), Word("topic"), Word("SEND"),
                                Word("topic"), Word("UNSUBSCRIBE")
                            ]).into();
                            let mut buf = [0u8; 4];

                            BigEndian::write_u32(&mut buf, msg.len() as u32);
                            stream.write_all(buf.as_ref()).unwrap();
                            stream.write_all(msg.as_ref()).unwrap();

                            stream.read(&mut buf).unwrap();

                            let msg_len = BigEndian::read_u32(&mut buf);

                            let s_ref = <TcpStream as Read>::by_ref(&mut stream);

                            r.clear();

                            match s_ref.take(msg_len as u64).read_to_end(&mut r) {
                                Ok(0) => {
                                },
                                Ok(_) => {
                                    let mut input = r.clone();
                                    let mut top_level = true;
                                    let mut s = String::new();
                                    while input.len()> 0 {
                                        match script::binparser::data(input.clone().as_slice()) {
                                            nom::IResult::Done(rest, data) => {
                                                let (_, size) = script::binparser::data_size(data).unwrap();
                                                let data = &data[script::offset_by_size(size)..];

                                                input = Vec::from(rest);

                                                if rest.len() == 0 && top_level {
                                                    top_level = false;
                                                    if data.len() > 0 {
                                                        let _ = write!(&mut s, "{}", Red.paint("Error: "));
                                                        input = Vec::from(data);
                                                    }
                                                } else {
                                                    if data.iter().all(|c| *c >= 0x20 && *c <= 0x7e) {
                                                        let _ = write!(&mut s, "{:?} ", str::from_utf8(data).unwrap());
                                                    } else {
                                                        let _ = write!(&mut s, "0x");
                                                        for b in Vec::from(data) {
                                                            let _ = write!(&mut s, "{:02x}", b);
                                                        }
                                                        let _ = write!(&mut s, " ");
                                                    }
                                                }
                                            },
                                            e => {
                                                panic!("{:?}", e);
                                            }
                                        }
                                    }
                                    println!("{}", s);
                                },
                                Err(e) => {
                                    panic!("{}", e);
                                }
                            }
                        },
                        Err(err) => {
                            println!("Script error: {:?}", err);
                        }
                    }
                }
            }
            Err(ReadlineError::Interrupted) => {
                println!("Aborted");
                break
            },
            Err(ReadlineError::Eof) => {
                println!("Exiting");
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }

    }
}<|endoftext|>


<commit_before>use ast::{Expr, ConstExpr, BlockExpr, LocalExpr, GetConstFieldExpr, GetFieldExpr, CallExpr, WhileLoopExpr, IfExpr, SwitchExpr, ObjectDeclExpr, ArrayDeclExpr, FunctionDeclExpr, NumOpExpr, BitOpExpr, ConstructExpr, ReturnExpr, ThrowExpr, AssignExpr};
use ast::{CNum, CInt, CString, CBool, CRegExp, CNull, CUndefined};
use ast::{OpSub, OpAdd, OpMul, OpDiv, OpMod};
use ast::{BitAnd, BitOr, BitXor, BitShl, BitShr};
use js::value::{Value, VNull, VUndefined, VNumber, VString, VObject, VBoolean, VFunction, ResultValue};
use js::object::ObjectData;
use js::function::{RegularFunc, RegularFunction};
use js::{console, math, object, array, function, json, number, error, uri};
use collections::treemap::TreeMap;
use std::vec::Vec;
use std::gc::Gc;
use std::cell::RefCell;
/// An execution engine
pub trait Executor {
	/// Makes a new execution engine
	fn new() -> ~Self;
	/// Sets a global variable
	fn set_global(&mut self, name:~str, val:Value) -> Value;
	/// Gets a global variable
	fn get_global(&self, name:~str) -> Value;
	/// Make a new scope
	fn make_scope(&mut self) -> Gc<RefCell<ObjectData>>;
	/// Destroy the current scope
	fn destroy_scope(&mut self) -> ();
	/// Runs the expression
	fn run(&mut self, expr:&Expr) -> ResultValue;
}
/// An intepreter
pub struct Interpreter {
	/// An object representing the global variables
	global: Value,
	/// The scopes
	scopes: Vec<Gc<RefCell<ObjectData>>>,
}
impl Executor for Interpreter {
	fn new() -> ~Interpreter {
		let mut globals : ObjectData = TreeMap::new();
		globals.insert(~"console", console::_create());
		globals.insert(~"Math", math::_create());
		globals.insert(~"Object", object::_create());
		globals.insert(~"Array", array::_create());
		globals.insert(~"Function", function::_create());
		globals.insert(~"JSON", json::_create());
		globals.insert(~"Number", number::_create());
		globals.insert(~"Error", error::_create());
		let global = Gc::new(VObject(RefCell::new(globals)));
		number::init(global);
		uri::init(global);
		return ~Interpreter {global: global, scopes: Vec::new()};
	}
	fn set_global(&mut self, name:~str, val:Value) -> Value {
		self.global.borrow().set_field(name, val)
	}
	fn get_global(&self, name:~str) -> Value {
		self.global.borrow().get_field(name)
	}
	fn make_scope(&mut self) -> Gc<RefCell<ObjectData>> {
		let mut data = TreeMap::new();
		let value = Gc::new(RefCell::new(data));
		self.scopes.push(value.clone());
		value
	}
	fn destroy_scope(&mut self) -> () {
		self.scopes.pop();
	}
	fn run(&mut self, expr:&Expr) -> ResultValue {
		match *expr {
			ConstExpr(CNull) => Ok(Gc::new(VNull)),
			ConstExpr(CUndefined) => Ok(Gc::new(VUndefined)),
			ConstExpr(CNum(num)) => Ok(Gc::new(VNumber(num))),
			ConstExpr(CInt(num)) => Ok(Gc::new(VNumber(num as f64))),
			ConstExpr(CString(ref str)) => Ok(Gc::new(VString(str.to_owned()))),
			ConstExpr(CBool(val)) => Ok(Gc::new(VBoolean(val))),
			ConstExpr(CRegExp(ref reg, _, _)) => Ok(Gc::new(VBoolean(true))),
			BlockExpr(ref es) => {
				let mut obj = Gc::new(VNull);
				for e in es.iter() {
					let val = try!(self.run(*e));
					if e == es.last().unwrap() {
						obj = val;
					}
				}
				Ok(obj)
			},
			LocalExpr(ref name) => {
				let mut value = Gc::new(VUndefined);
				for scope in self.scopes.iter().rev() {
					match scope.borrow().borrow().find(name) {
						Some(v) => {
							value = v.clone();
							break;
						}
						None => ()
					}
				}
				Ok(if value.borrow() == &VUndefined {
					self.global.borrow().get_field(name.clone())
				} else {
					value
				})
			},
			GetConstFieldExpr(ref obj, ref field) => {
				let val_obj = try!(self.run(*obj));
				Ok(val_obj.borrow().get_field(field.clone()))
			},
			GetFieldExpr(ref obj, ref field) => {
				let val_obj = try!(self.run(*obj));
				let val_field = try!(self.run(*field));
				Ok(val_obj.borrow().get_field(val_field.borrow().to_str()))
			},
			CallExpr(ref callee, ref args) => {
				let (this, func) = match **callee {
					GetConstFieldExpr(ref obj, ref field) => {
						let obj = try!(self.run(*obj));
						(obj, obj.borrow().get_field(field.clone()))
					},
					GetFieldExpr(ref obj, ref field) => {
						let obj = try!(self.run(*obj));
						let field = try!(self.run(*field));
						(obj, obj.borrow().get_field(field.borrow().to_str()))
					},
					_ => (self.global.clone(), try!(self.run(callee.clone())))
				};
				let mut v_args = Vec::with_capacity(args.len());
				for arg in args.iter() {
					v_args.push(try!(self.run(*arg)));
				}
				match *func.borrow() {
					VFunction(ref func) => {
						func.borrow().call(self, this, Gc::new(VNull), v_args)
					},
					_ => Err(Gc::new(VUndefined))
				}
			},
			WhileLoopExpr(ref cond, ref expr) => {
				let mut result = Gc::new(VUndefined);
				while try!(self.run(*cond)).borrow().is_true() {
					result = try!(self.run(*expr));
				}
				Ok(result)
			},
			IfExpr(ref cond, ref expr, None) => {
				Ok(if try!(self.run(*cond)).borrow().is_true() {
					try!(self.run(*expr))
				} else {
					Gc::new(VUndefined)
				})
			},
			IfExpr(ref cond, ref expr, Some(ref else_e)) => {
				Ok(if try!(self.run(*cond)).borrow().is_true() {
					try!(self.run(*expr))
				} else {
					try!(self.run(*else_e))
				})
			},
			SwitchExpr(ref val_e, ref vals, ref default) => {
				let val = try!(self.run(*val_e)).borrow().clone();
				let mut result = Gc::new(VNull);
				let mut matched = false;
				for tup in vals.iter() {
					let tup:&(~Expr, Vec<~Expr>) = tup;
					match *tup {
						(ref cond, ref block) if(val == *try!(self.run(*cond)).borrow()) => {
							matched = true;
							let last_expr = block.last().unwrap();
							for expr in block.iter() {
								let e_result = try!(self.run(*expr));
								if expr == last_expr {
									result = e_result;
								}
							}
						},
						_ => ()
					}
				}
				if !matched && default.is_some() {
					result = try!(self.run(*default.as_ref().unwrap()));
				}
				Ok(result)
			},
			ObjectDeclExpr(ref map) => {
				let mut obj = TreeMap::new();
				for (key, val) in map.iter() {
					obj.insert(key.clone(), try!(self.run(val.clone())));
				}
				obj.swap(~"__proto__", self.get_global(~"Object").borrow().get_field(~"prototype"));
				Ok(Gc::new(VObject(RefCell::new(obj))))
			},
			ArrayDeclExpr(ref arr) => {
				let mut arr_map = TreeMap::new();
				let mut index = 0;
				for val in arr.iter() {
					let val = try!(self.run(val.clone()));
					arr_map.insert(index.to_str(), val);
					index += 1;
				}
				arr_map.insert(~"__proto__", self.get_global(~"Array").borrow().get_field(~"prototype"));
				Ok(Gc::new(VObject(RefCell::new(arr_map))))
			},
			FunctionDeclExpr(ref name, ref args, ref expr) => {
				let function = RegularFunc(RegularFunction::new(*expr.clone(), args.clone()));
				let val = Gc::new(VFunction(RefCell::new(function)));
				if name.is_some() {
					self.global.borrow().set_field(name.clone().unwrap(), val);
				}
				Ok(val)
			},
			NumOpExpr(ref op, ref a, ref b) => {
				let v_a = try!(self.run(*a)).borrow().clone();
				let v_b = try!(self.run(*b)).borrow().clone();
				Ok(Gc::new(match *op {
					OpAdd => v_a + v_b,
					OpSub => v_a - v_b,
					OpMul => v_a * v_b,
					OpDiv => v_a / v_b,
					OpMod => v_a % v_b
				}))
			},
			BitOpExpr(ref op, ref a, ref b) => {
				let v_a = try!(self.run(*a)).borrow().clone();
				let v_b = try!(self.run(*b)).borrow().clone();
				Ok(Gc::new(match *op {
					BitAnd => v_a & v_b,
					BitOr => v_a | v_b,
					BitXor => v_a ^ v_b,
					BitShl => v_a << v_b,
					BitShr => v_a >> v_b
				}))
			},
			ConstructExpr(ref callee, ref args) => {
				let func = try!(self.run(callee.clone()));
				let mut v_args = Vec::with_capacity(args.len());
				for arg in args.iter() {
					v_args.push(try!(self.run(*arg)));
				}
				let this = Gc::new(VObject(RefCell::new(TreeMap::new())));
				this.borrow().set_field(~"__proto__", func.borrow().get_field(~"prototype"));
				Ok(match *func.borrow() {
					VFunction(ref func) => {
						func.borrow().call(self, this, Gc::new(VNull), v_args).unwrap();
						this
					},
					_ => Gc::new(VUndefined)
				})
			},
			ReturnExpr(ref ret) => {
				match *ret {
					Some(ref v) =>
						self.run(v.clone()),
					None => Ok(Gc::new(VUndefined))
				}
			},
			ThrowExpr(ref ex) => Err(try!(self.run(*ex))),
			AssignExpr(ref ref_e, ref val_e) => {
				let val = try!(self.run(*val_e));
				match **ref_e {
					LocalExpr(ref name) => {
						self.global.borrow().set_field(name.clone(), val);
					},
					GetConstFieldExpr(ref obj, ref field) => {
						let val_obj = try!(self.run(*obj));
						val_obj.borrow().set_field(field.clone(), val);
					},
					_ => ()
				}
				Ok(val)
			}
		}
	}
}<commit_msg>Add length property to arrays<commit_after>use ast::{Expr, ConstExpr, BlockExpr, LocalExpr, GetConstFieldExpr, GetFieldExpr, CallExpr, WhileLoopExpr, IfExpr, SwitchExpr, ObjectDeclExpr, ArrayDeclExpr, FunctionDeclExpr, NumOpExpr, BitOpExpr, ConstructExpr, ReturnExpr, ThrowExpr, AssignExpr};
use ast::{CNum, CInt, CString, CBool, CRegExp, CNull, CUndefined};
use ast::{OpSub, OpAdd, OpMul, OpDiv, OpMod};
use ast::{BitAnd, BitOr, BitXor, BitShl, BitShr};
use js::value::{Value, VNull, VUndefined, VNumber, VInteger, VString, VObject, VBoolean, VFunction, ResultValue};
use js::object::ObjectData;
use js::function::{RegularFunc, RegularFunction};
use js::{console, math, object, array, function, json, number, error, uri};
use collections::treemap::TreeMap;
use std::vec::Vec;
use std::gc::Gc;
use std::cell::RefCell;
/// An execution engine
pub trait Executor {
	/// Makes a new execution engine
	fn new() -> ~Self;
	/// Sets a global variable
	fn set_global(&mut self, name:~str, val:Value) -> Value;
	/// Gets a global variable
	fn get_global(&self, name:~str) -> Value;
	/// Make a new scope
	fn make_scope(&mut self) -> Gc<RefCell<ObjectData>>;
	/// Destroy the current scope
	fn destroy_scope(&mut self) -> ();
	/// Runs the expression
	fn run(&mut self, expr:&Expr) -> ResultValue;
}
/// An intepreter
pub struct Interpreter {
	/// An object representing the global variables
	global: Value,
	/// The scopes
	scopes: Vec<Gc<RefCell<ObjectData>>>,
}
impl Executor for Interpreter {
	fn new() -> ~Interpreter {
		let mut globals : ObjectData = TreeMap::new();
		globals.insert(~"console", console::_create());
		globals.insert(~"Math", math::_create());
		globals.insert(~"Object", object::_create());
		globals.insert(~"Array", array::_create());
		globals.insert(~"Function", function::_create());
		globals.insert(~"JSON", json::_create());
		globals.insert(~"Number", number::_create());
		globals.insert(~"Error", error::_create());
		let global = Gc::new(VObject(RefCell::new(globals)));
		number::init(global);
		uri::init(global);
		return ~Interpreter {global: global, scopes: Vec::new()};
	}
	fn set_global(&mut self, name:~str, val:Value) -> Value {
		self.global.borrow().set_field(name, val)
	}
	fn get_global(&self, name:~str) -> Value {
		self.global.borrow().get_field(name)
	}
	fn make_scope(&mut self) -> Gc<RefCell<ObjectData>> {
		let mut data = TreeMap::new();
		let value = Gc::new(RefCell::new(data));
		self.scopes.push(value.clone());
		value
	}
	fn destroy_scope(&mut self) -> () {
		self.scopes.pop();
	}
	fn run(&mut self, expr:&Expr) -> ResultValue {
		match *expr {
			ConstExpr(CNull) => Ok(Gc::new(VNull)),
			ConstExpr(CUndefined) => Ok(Gc::new(VUndefined)),
			ConstExpr(CNum(num)) => Ok(Gc::new(VNumber(num))),
			ConstExpr(CInt(num)) => Ok(Gc::new(VNumber(num as f64))),
			ConstExpr(CString(ref str)) => Ok(Gc::new(VString(str.to_owned()))),
			ConstExpr(CBool(val)) => Ok(Gc::new(VBoolean(val))),
			ConstExpr(CRegExp(ref reg, _, _)) => Ok(Gc::new(VBoolean(true))),
			BlockExpr(ref es) => {
				let mut obj = Gc::new(VNull);
				for e in es.iter() {
					let val = try!(self.run(*e));
					if e == es.last().unwrap() {
						obj = val;
					}
				}
				Ok(obj)
			},
			LocalExpr(ref name) => {
				let mut value = Gc::new(VUndefined);
				for scope in self.scopes.iter().rev() {
					match scope.borrow().borrow().find(name) {
						Some(v) => {
							value = v.clone();
							break;
						}
						None => ()
					}
				}
				Ok(if value.borrow() == &VUndefined {
					self.global.borrow().get_field(name.clone())
				} else {
					value
				})
			},
			GetConstFieldExpr(ref obj, ref field) => {
				let val_obj = try!(self.run(*obj));
				Ok(val_obj.borrow().get_field(field.clone()))
			},
			GetFieldExpr(ref obj, ref field) => {
				let val_obj = try!(self.run(*obj));
				let val_field = try!(self.run(*field));
				Ok(val_obj.borrow().get_field(val_field.borrow().to_str()))
			},
			CallExpr(ref callee, ref args) => {
				let (this, func) = match **callee {
					GetConstFieldExpr(ref obj, ref field) => {
						let obj = try!(self.run(*obj));
						(obj, obj.borrow().get_field(field.clone()))
					},
					GetFieldExpr(ref obj, ref field) => {
						let obj = try!(self.run(*obj));
						let field = try!(self.run(*field));
						(obj, obj.borrow().get_field(field.borrow().to_str()))
					},
					_ => (self.global.clone(), try!(self.run(callee.clone())))
				};
				let mut v_args = Vec::with_capacity(args.len());
				for arg in args.iter() {
					v_args.push(try!(self.run(*arg)));
				}
				match *func.borrow() {
					VFunction(ref func) => {
						func.borrow().call(self, this, Gc::new(VNull), v_args)
					},
					_ => Err(Gc::new(VUndefined))
				}
			},
			WhileLoopExpr(ref cond, ref expr) => {
				let mut result = Gc::new(VUndefined);
				while try!(self.run(*cond)).borrow().is_true() {
					result = try!(self.run(*expr));
				}
				Ok(result)
			},
			IfExpr(ref cond, ref expr, None) => {
				Ok(if try!(self.run(*cond)).borrow().is_true() {
					try!(self.run(*expr))
				} else {
					Gc::new(VUndefined)
				})
			},
			IfExpr(ref cond, ref expr, Some(ref else_e)) => {
				Ok(if try!(self.run(*cond)).borrow().is_true() {
					try!(self.run(*expr))
				} else {
					try!(self.run(*else_e))
				})
			},
			SwitchExpr(ref val_e, ref vals, ref default) => {
				let val = try!(self.run(*val_e)).borrow().clone();
				let mut result = Gc::new(VNull);
				let mut matched = false;
				for tup in vals.iter() {
					let tup:&(~Expr, Vec<~Expr>) = tup;
					match *tup {
						(ref cond, ref block) if(val == *try!(self.run(*cond)).borrow()) => {
							matched = true;
							let last_expr = block.last().unwrap();
							for expr in block.iter() {
								let e_result = try!(self.run(*expr));
								if expr == last_expr {
									result = e_result;
								}
							}
						},
						_ => ()
					}
				}
				if !matched && default.is_some() {
					result = try!(self.run(*default.as_ref().unwrap()));
				}
				Ok(result)
			},
			ObjectDeclExpr(ref map) => {
				let mut obj = TreeMap::new();
				for (key, val) in map.iter() {
					obj.insert(key.clone(), try!(self.run(val.clone())));
				}
				obj.swap(~"__proto__", self.get_global(~"Object").borrow().get_field(~"prototype"));
				Ok(Gc::new(VObject(RefCell::new(obj))))
			},
			ArrayDeclExpr(ref arr) => {
				let mut arr_map = TreeMap::new();
				let mut index : i32 = 0;
				for val in arr.iter() {
					let val = try!(self.run(val.clone()));
					arr_map.insert(index.to_str(), val);
					index += 1;
				}
				arr_map.insert(~"__proto__", self.get_global(~"Array").borrow().get_field(~"prototype"));
				arr_map.insert(~"length", Gc::new(VInteger(index)));
				Ok(Gc::new(VObject(RefCell::new(arr_map))))
			},
			FunctionDeclExpr(ref name, ref args, ref expr) => {
				let function = RegularFunc(RegularFunction::new(*expr.clone(), args.clone()));
				let val = Gc::new(VFunction(RefCell::new(function)));
				if name.is_some() {
					self.global.borrow().set_field(name.clone().unwrap(), val);
				}
				Ok(val)
			},
			NumOpExpr(ref op, ref a, ref b) => {
				let v_a = try!(self.run(*a)).borrow().clone();
				let v_b = try!(self.run(*b)).borrow().clone();
				Ok(Gc::new(match *op {
					OpAdd => v_a + v_b,
					OpSub => v_a - v_b,
					OpMul => v_a * v_b,
					OpDiv => v_a / v_b,
					OpMod => v_a % v_b
				}))
			},
			BitOpExpr(ref op, ref a, ref b) => {
				let v_a = try!(self.run(*a)).borrow().clone();
				let v_b = try!(self.run(*b)).borrow().clone();
				Ok(Gc::new(match *op {
					BitAnd => v_a & v_b,
					BitOr => v_a | v_b,
					BitXor => v_a ^ v_b,
					BitShl => v_a << v_b,
					BitShr => v_a >> v_b
				}))
			},
			ConstructExpr(ref callee, ref args) => {
				let func = try!(self.run(callee.clone()));
				let mut v_args = Vec::with_capacity(args.len());
				for arg in args.iter() {
					v_args.push(try!(self.run(*arg)));
				}
				let this = Gc::new(VObject(RefCell::new(TreeMap::new())));
				this.borrow().set_field(~"__proto__", func.borrow().get_field(~"prototype"));
				Ok(match *func.borrow() {
					VFunction(ref func) => {
						func.borrow().call(self, this, Gc::new(VNull), v_args).unwrap();
						this
					},
					_ => Gc::new(VUndefined)
				})
			},
			ReturnExpr(ref ret) => {
				match *ret {
					Some(ref v) =>
						self.run(v.clone()),
					None => Ok(Gc::new(VUndefined))
				}
			},
			ThrowExpr(ref ex) => Err(try!(self.run(*ex))),
			AssignExpr(ref ref_e, ref val_e) => {
				let val = try!(self.run(*val_e));
				match **ref_e {
					LocalExpr(ref name) => {
						self.global.borrow().set_field(name.clone(), val);
					},
					GetConstFieldExpr(ref obj, ref field) => {
						let val_obj = try!(self.run(*obj));
						val_obj.borrow().set_field(field.clone(), val);
					},
					_ => ()
				}
				Ok(val)
			}
		}
	}
}<|endoftext|>