<commit_before>use std::process::Command;
use std::fs::File;
use std::io::Write;

#[derive(PartialEq)]
enum OpType {
    Word,
    Long,
}

#[derive(PartialEq, Clone)]
enum EaType {
    Any,
    Immidate,
    DataRegister,
    AddressRegister,
    Memory,
}

struct Op {
    name: &'static str,
    count: usize,
    ea_type: EaType,
}

impl Op {
    fn new(name: &'static str, count: usize, ea_type: EaType) -> Op {
        Op {
            name: name,
            count: count,
            ea_type: ea_type,
        }
    }
}

#[derive(Clone)]
struct CycleRule {
    count: usize,
    source: EaType,
    dest: EaType,
}

struct Instruction<'a> {
    name: &'static str,
    op_type: OpType,
    cycle_rules: &'a [CycleRule],
}

fn calculate_cycle_count(inst: &Instruction, src: &Op, dest: &Op) -> usize {
    let mut cycle_count = 0;

    for rule in inst.cycle_rules {
        if (src.ea_type == rule.source || rule.source == EaType::Any) &&
           (dest.ea_type == rule.dest || rule.dest == EaType::Any) {
            cycle_count = rule.count;
            break;
        }
    }

    cycle_count += src.count + dest.count;

    if inst.op_type == OpType::Long {
        if src.count != 0 {
            cycle_count += 4;
        }

        if dest.count != 0 {
            cycle_count += 4;
        }
    }

    cycle_count
}

fn main() {
    let dest_types = [Op::new("d0", 0, EaType::DataRegister),
                      Op::new("a0", 0, EaType::AddressRegister),
                      Op::new("(a0)", 4, EaType::Memory),
                      Op::new("(a0)+", 4, EaType::Memory),
                      Op::new("-(a0)", 6, EaType::Memory),
                      Op::new("2(a0)", 8, EaType::Memory),
                      Op::new("2(a0,d0)", 10, EaType::Memory),
                      Op::new("$4.W", 8, EaType::Memory),
                      Op::new("$4.L", 12, EaType::Memory)];

    let src_types = [Op::new("d0", 0, EaType::DataRegister),
                     Op::new("a0", 0, EaType::AddressRegister),
                     Op::new("(a0)", 4, EaType::Memory),
                     Op::new("(a0)+", 4, EaType::Memory),
                     Op::new("-(a0)", 6, EaType::Memory),
                     Op::new("2(a0)", 8, EaType::Memory),
                     Op::new("2(a0,d0)", 10, EaType::Memory),
                     Op::new("$4.W", 8, EaType::Memory),
                     Op::new("$4.L", 12, EaType::Memory),
                     Op::new("2(pc)", 8, EaType::Memory),
                     Op::new("2(pc,d0)", 10, EaType::Memory),
                     Op::new("#2", 4, EaType::Immidate)];

    let mut compile_status = Vec::new();

    let filename = "temp.s";

    let dst_print = [" Dn ",
                     " An ",
                     " (An) ",
                     " (An)+ ",
                     " -(An) ",
                     " d(An) ",
                     " d(An,Dn) ",
                     " xxx.W ",
                     " xxx.L "];
    let src_print = ["| Dn       ",
                     "| An       ",
                     "| (An)     ",
                     "| (An)+    ",
                     "| -(An)    ",
                     "| d(An)    ",
                     "| d(An,Dn) ",
                     "| xxx.W    ",
                     "| xxx.L    ",
                     "| d(Pc)    ",
                     "| d(Pc,Dn) ",
                     "| #xxx     "];

    let instructions = [// Instruction {
                        // name: "clr.w",
                        // op_type: OpType::Word,
                        // cycle_rules: &[
                        // CycleRule { count: 4, source: EaType::DataRegister, dest: EaType::Any },
                        // CycleRule { count: 8, source: EaType::DataRegister, dest: EaType::Memory },
                        // ]
                        // },
                        //
                        Instruction {
                            name: "add.w",
                            op_type: OpType::Word,
                            cycle_rules: &[CycleRule {
                                               count: 4,
                                               source: EaType::Immidate,
                                               dest: EaType::DataRegister,
                                           },
                                           CycleRule {
                                               count: 8,
                                               source: EaType::Immidate,
                                               dest: EaType::Memory,
                                           },
                                           CycleRule {
                                               count: 8,
                                               source: EaType::Any,
                                               dest: EaType::AddressRegister,
                                           },
                                           CycleRule {
                                               count: 4,
                                               source: EaType::Any,
                                               dest: EaType::DataRegister,
                                           },
                                           CycleRule {
                                               count: 8,
                                               source: EaType::DataRegister,
                                               dest: EaType::Memory,
                                           }],
                        },
                        Instruction {
                            name: "add.l",
                            op_type: OpType::Long,
                            cycle_rules: &[CycleRule {
                                               count: 8,
                                               source: EaType::Immidate,
                                               dest: EaType::DataRegister,
                                           },
                                           CycleRule {
                                               count: 8,
                                               source: EaType::Immidate,
                                               dest: EaType::Memory,
                                           },
                                           CycleRule {
                                               count: 8,
                                               source: EaType::Any,
                                               dest: EaType::AddressRegister,
                                           },
                                           CycleRule {
                                               count: 6,
                                               source: EaType::Any,
                                               dest: EaType::DataRegister,
                                           },
                                           CycleRule {
                                               count: 12,
                                               source: EaType::DataRegister,
                                               dest: EaType::Memory,
                                           }],
                        } /* Instruction {
                           * name: "and.l",
                           * op_type: OpType::Word,
                           * cycle_rules: &[
                           * CycleRule { count: 6, source: EaType::Any, dest: EaType::DataRegister },
                           * CycleRule { count: 12, source: EaType::DataRegister, dest: EaType::Memory },
                           * ]
                           * }
                           * */];

    for inst in &instructions {
        compile_status.clear();
        for src in &src_types {
            for dst in &dest_types {

                {
                    let mut file = File::create(filename).unwrap();
                    write!(file, " {} {},{}", inst.name, src.name, dst.name).unwrap();
                }

                let output = Command::new("vasmm68k_mot")
                    .arg("-quiet")
                    .arg(filename)
                    .output()
                    .expect("failed to execute process");

                if output.status.success() {
                    compile_status.push(Some(calculate_cycle_count(&inst, &src, &dst)));
                } else {
                    compile_status.push(None);
                }
            }
        }

        // print header
        print!("| {name:<width$}", name = inst.name, width = 9);

        for dst in &dst_print {
            print!("|{}", dst);
        }

        println!("|");
        println!("|----------|----|----|------|-------|-------|-------|----------|-------|-------|");

        let mut index = 0;

        for src in &src_print {
            print!("{}", src);

            for dest_name in &dst_print {
                if let Some(cycle_count) = compile_status[index] {
                    print!("|{number:^width$}",
                           number = cycle_count,
                           width = dest_name.len());
                } else {
                    print!("|{number:^width$}", number = "*", width = dest_name.len());
                }
                index += 1;
            }

            println!("|");
        }

        println!("");
    }
}
<commit_msg>Cleanup<commit_after>use std::process::Command;
use std::fs::File;
use std::io::Write;

#[derive(PartialEq, Clone)]
enum Ea {
    Any,
    Immidate,
    DataRegister,
    AddressRegister,
    Memory,
}

#[derive(PartialEq, Copy, Clone)]
enum Size {
    _Byte,
    Word,
    Long,
}

struct Op {
    name: &'static str,
    print_name: &'static str,
    count: usize,
    ea_type: Ea,
}

impl Op {
    fn new(name: &'static str, print_name: &'static str, count: usize, ea_type: Ea) -> Op {
        Op {
            name: name,
            print_name: print_name,
            count: count,
            ea_type: ea_type,
        }
    }
}

#[derive(Clone)]
struct CycleRule {
    word_count: usize,
    long_count: usize,
    source: Ea,
    dest: Ea,
}

impl CycleRule {
    fn new(word_count: usize, long_count: usize, source: Ea, dest: Ea) -> CycleRule {
        CycleRule {
            word_count: word_count,
            long_count: long_count,
            source: source,
            dest: dest,
        }
    }
}

struct Instruction<'a> {
    name: &'static str,
    cycle_rules: &'a [CycleRule],
}

fn calculate_cycle_count(inst: &Instruction, src: &Op, dest: &Op, size: Size) -> usize {
    let mut cycle_count = 0;

    for rule in inst.cycle_rules {
        if (src.ea_type == rule.source || rule.source == Ea::Any) &&
           (dest.ea_type == rule.dest || rule.dest == Ea::Any) {
            match size {
                Size::Word => cycle_count = rule.word_count,
                Size::Long => cycle_count = rule.long_count,
                _ => panic!("Not supported!"),
            }
            break;
        }
    }

    cycle_count += src.count + dest.count;

    if size == Size::Long {
        if src.count != 0 {
            cycle_count += 4;
        }

        if dest.count != 0 {
            cycle_count += 4;
        }
    }

    cycle_count
}

fn compile_statement(statement: &str) -> bool {
    let filename = "temp.s";

    {
        let mut file = File::create(filename).unwrap();
        write!(file, " {}", statement).unwrap();
    }

    let output =
        Command::new("vasmm68k_mot").arg(filename).output().expect("failed to execute process");

    output.status.success()
}

fn print_grid_table(name: &str, cycles: &Vec<Option<usize>>, src_table: &[Op], dest_table: &[Op]) {
    print!("| {name:<width$}", name = name, width = 9);

    for dst in dest_table {
        print!("| {} ", dst.print_name);
    }

    println!("|");
    println!("|----------|----|----|------|-------|-------|-------|----------|-------|-------|");

    let mut index = 0;

    for src in src_table {
        print!("| {name:<width$}", name = src.print_name, width = 9);

        for dest in dest_table {
            if let Some(cycle_count) = cycles[index] {
                print!("|{number:^width$}",
                       number = cycle_count,
                       width = dest.print_name.len() + 2);
            } else {
                print!("|{number:^width$}",
                       number = "*",
                       width = dest.print_name.len() + 2);
            }
            index += 1;
        }

        println!("|");
    }

    println!("");
}

fn generate_table(inst: &Instruction,
                  name: &str,
                  size: Size,
                  src_table: Option<&[Op]>,
                  dest_table: &[Op]) {
    let mut cycles = Vec::with_capacity(20 * 20);

    if let Some(src_opts) = src_table {
        for src in src_opts {
            for dst in dest_table {
                let statement = format!("{} {},{}", name, src.name, dst.name);
                if compile_statement(&statement) {
                    cycles.push(Some(calculate_cycle_count(inst, &src, &dst, size)));
                } else {
                    cycles.push(None);
                }
            }
        }

        print_grid_table(name, &cycles, &src_opts, dest_table);
    }
}

fn main() {
    let dest_types = [Op::new("d0", "Dn", 0, Ea::DataRegister),
                      Op::new("a0", "An", 0, Ea::AddressRegister),
                      Op::new("(a0)", "(An)", 4, Ea::Memory),
                      Op::new("(a0)+", "(An)+", 4, Ea::Memory),
                      Op::new("-(a0)", "-(An)", 6, Ea::Memory),
                      Op::new("2(a0)", "d(An)", 8, Ea::Memory),
                      Op::new("2(a0,d0)", "d(An,Dn)", 10, Ea::Memory),
                      Op::new("$4.W", "xxx.W", 8, Ea::Memory),
                      Op::new("$4.L", "xxx.L", 12, Ea::Memory)];

    let src_types = [Op::new("d0", "Dn", 0, Ea::DataRegister),
                     Op::new("a0", "An", 0, Ea::AddressRegister),
                     Op::new("(a0)", "(An)", 4, Ea::Memory),
                     Op::new("(a0)+", "(An)+", 4, Ea::Memory),
                     Op::new("-(a0)", "-(An)", 6, Ea::Memory),
                     Op::new("2(a0)", "d(An)", 8, Ea::Memory),
                     Op::new("2(a0,d0)", "d(An,Dn)", 10, Ea::Memory),
                     Op::new("$4.W", "xxx.W", 8, Ea::Memory),
                     Op::new("$4.L", "xxx.L", 12, Ea::Memory),
                     Op::new("2(pc)", "d(PC)", 8, Ea::Memory),
                     Op::new("2(pc,d0)", "d(PC,Dn)", 10, Ea::Memory),
                     Op::new("#2", "#xxx", 4, Ea::Immidate)];

    let inst_2_ops_00 = [Instruction {
                             name: "add",
                             cycle_rules: &[CycleRule::new(4, 8, Ea::Immidate, Ea::DataRegister),
                                            CycleRule::new(8, 8, Ea::Immidate, Ea::Memory),
                                            CycleRule::new(8, 8, Ea::Any, Ea::AddressRegister),
                                            CycleRule::new(4, 6, Ea::Any, Ea::DataRegister),
                                            CycleRule::new(8, 12, Ea::DataRegister, Ea::Memory)],
                         }];

    for inst in &inst_2_ops_00 {
        // generate for .w and .l

        let name_word = format!("{}.w", inst.name);
        let name_long = format!("{}.l", inst.name);

        generate_table(&inst, &name_word, Size::Word, Some(&src_types), &dest_types);
        generate_table(&inst, &name_long, Size::Long, Some(&src_types), &dest_types);

    }
}
<|endoftext|>


<commit_before>use object;

use geometry::Geometry;
use hub::Operation;
use material::Material;
use render::DynamicData;
use skeleton::Skeleton;

use std::hash::{Hash, Hasher};

/// [`Geometry`](struct.Geometry.html) with some [`Material`](struct.Material.html).
///
/// # Examples
///
/// Creating a solid red triangle.
///
/// ```rust,no_run
/// # let mut win = three::Window::new("Example");
/// # let factory = &mut win.factory;
/// let vertices = vec![
///     [-0.5, -0.5, 0.0].into(),
///     [ 0.5, -0.5, 0.0].into(),
///     [ 0.5, -0.5, 0.0].into(),
/// ];
/// let geometry = three::Geometry::with_vertices(vertices);
/// let red_material = three::material::Basic { color: three::color::RED, map: None };
/// let mesh = factory.mesh(geometry, red_material);
/// # let _ = mesh;
/// ```
///
/// Duplicating a mesh.
///
/// ```rust,no_run
/// # let mut win = three::Window::new("Example");
/// # let factory = &mut win.factory;
/// # let vertices = vec![
/// #     [-0.5, -0.5, 0.0].into(),
/// #     [ 0.5, -0.5, 0.0].into(),
/// #     [ 0.5, -0.5, 0.0].into(),
/// # ];
/// # let geometry = three::Geometry::with_vertices(vertices);
/// # let red_material = three::material::Basic { color: three::color::RED, map: None };
/// # let mesh = factory.mesh(geometry, red_material);
/// use three::Object;
/// let mut duplicate = factory.mesh_instance(&mesh);
/// // Duplicated meshes share their geometry but may be transformed individually.
/// duplicate.set_position([1.2, 3.4, 5.6]);
/// ```
///
/// Duplicating a mesh with a different material.
///
/// ```rust,no_run
/// # let mut win = three::Window::new("Example");
/// # let factory = &mut win.factory;
/// # let vertices = vec![
/// #     [-0.5, -0.5, 0.0].into(),
/// #     [ 0.5, -0.5, 0.0].into(),
/// #     [ 0.5, -0.5, 0.0].into(),
/// # ];
/// # let geometry = three::Geometry::with_vertices(vertices);
/// # let red_material = three::material::Basic { color: three::color::RED, map: None };
/// # let mesh = factory.mesh(geometry, red_material);
/// let yellow_material = three::material::Wireframe { color: three::color::YELLOW };
/// # use three::Object;
/// let mut duplicate = factory.mesh_instance_with_material(&mesh, yellow_material);
/// duplicate.set_position([1.2, 3.4, 5.6]);
/// ```
///
/// # Notes
///
/// * Meshes are removed from the scene when dropped.
/// * Hence, meshes must be kept in scope in order to be displayed.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Mesh {
    pub(crate) object: object::Base,
}
three_object!(Mesh::object);

/// A dynamic version of a mesh allows changing the geometry on CPU side
/// in order to animate the mesh.
#[derive(Clone, Debug)]
pub struct DynamicMesh {
    pub(crate) object: object::Base,
    pub(crate) geometry: Geometry,
    pub(crate) dynamic: DynamicData,
}
three_object!(DynamicMesh::object);

impl PartialEq for DynamicMesh {
    fn eq(
        &self,
        other: &DynamicMesh,
    ) -> bool {
        self.object == other.object
    }
}

impl Eq for DynamicMesh {}

impl Hash for DynamicMesh {
    fn hash<H: Hasher>(
        &self,
        state: &mut H,
    ) {
        self.object.hash(state);
    }
}

impl Mesh {
    /// Set mesh material.
    pub fn set_material<M: Into<Material>>(
        &self,
        material: M,
    ) {
        self.as_ref().send(Operation::SetMaterial(material.into()));
    }

    /// Bind a skeleton to the mesh.
    pub fn set_skeleton(
        &self,
        skeleton: Skeleton,
    ) {
        self.as_ref().send(Operation::SetSkeleton(skeleton));
    }
}

impl DynamicMesh {
    /// Returns the number of vertices of the geometry base shape.
    pub fn vertex_count(&self) -> usize {
        self.geometry.base.vertices.len()
    }

    /// Set mesh material.
    pub fn set_material<M: Into<Material>>(
        &mut self,
        material: M,
    ) {
        self.as_ref().send(Operation::SetMaterial(material.into()));
    }
}
<commit_msg>Downcast meshes<commit_after>use geometry::Geometry;
use hub::Operation;
use material::Material;
use object::{self, DowncastObject, ObjectType};
use render::DynamicData;
use skeleton::Skeleton;

use std::hash::{Hash, Hasher};

/// [`Geometry`](struct.Geometry.html) with some [`Material`](struct.Material.html).
///
/// # Examples
///
/// Creating a solid red triangle.
///
/// ```rust,no_run
/// # let mut win = three::Window::new("Example");
/// # let factory = &mut win.factory;
/// let vertices = vec![
///     [-0.5, -0.5, 0.0].into(),
///     [ 0.5, -0.5, 0.0].into(),
///     [ 0.5, -0.5, 0.0].into(),
/// ];
/// let geometry = three::Geometry::with_vertices(vertices);
/// let red_material = three::material::Basic { color: three::color::RED, map: None };
/// let mesh = factory.mesh(geometry, red_material);
/// # let _ = mesh;
/// ```
///
/// Duplicating a mesh.
///
/// ```rust,no_run
/// # let mut win = three::Window::new("Example");
/// # let factory = &mut win.factory;
/// # let vertices = vec![
/// #     [-0.5, -0.5, 0.0].into(),
/// #     [ 0.5, -0.5, 0.0].into(),
/// #     [ 0.5, -0.5, 0.0].into(),
/// # ];
/// # let geometry = three::Geometry::with_vertices(vertices);
/// # let red_material = three::material::Basic { color: three::color::RED, map: None };
/// # let mesh = factory.mesh(geometry, red_material);
/// use three::Object;
/// let mut duplicate = factory.mesh_instance(&mesh);
/// // Duplicated meshes share their geometry but may be transformed individually.
/// duplicate.set_position([1.2, 3.4, 5.6]);
/// ```
///
/// Duplicating a mesh with a different material.
///
/// ```rust,no_run
/// # let mut win = three::Window::new("Example");
/// # let factory = &mut win.factory;
/// # let vertices = vec![
/// #     [-0.5, -0.5, 0.0].into(),
/// #     [ 0.5, -0.5, 0.0].into(),
/// #     [ 0.5, -0.5, 0.0].into(),
/// # ];
/// # let geometry = three::Geometry::with_vertices(vertices);
/// # let red_material = three::material::Basic { color: three::color::RED, map: None };
/// # let mesh = factory.mesh(geometry, red_material);
/// let yellow_material = three::material::Wireframe { color: three::color::YELLOW };
/// # use three::Object;
/// let mut duplicate = factory.mesh_instance_with_material(&mesh, yellow_material);
/// duplicate.set_position([1.2, 3.4, 5.6]);
/// ```
///
/// # Notes
///
/// * Meshes are removed from the scene when dropped.
/// * Hence, meshes must be kept in scope in order to be displayed.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Mesh {
    pub(crate) object: object::Base,
}
three_object!(Mesh::object);

impl DowncastObject for Mesh {
    fn downcast(object_type: ObjectType) -> Option<Mesh> {
        match object_type {
            ObjectType::Mesh(mesh) => Some(mesh),
            _ => None,
        }
    }
}

/// A dynamic version of a mesh allows changing the geometry on CPU side
/// in order to animate the mesh.
#[derive(Clone, Debug)]
pub struct DynamicMesh {
    pub(crate) object: object::Base,
    pub(crate) geometry: Geometry,
    pub(crate) dynamic: DynamicData,
}
three_object!(DynamicMesh::object);

impl PartialEq for DynamicMesh {
    fn eq(
        &self,
        other: &DynamicMesh,
    ) -> bool {
        self.object == other.object
    }
}

impl Eq for DynamicMesh {}

impl Hash for DynamicMesh {
    fn hash<H: Hasher>(
        &self,
        state: &mut H,
    ) {
        self.object.hash(state);
    }
}

impl Mesh {
    /// Set mesh material.
    pub fn set_material<M: Into<Material>>(
        &self,
        material: M,
    ) {
        self.as_ref().send(Operation::SetMaterial(material.into()));
    }

    /// Bind a skeleton to the mesh.
    pub fn set_skeleton(
        &self,
        skeleton: Skeleton,
    ) {
        self.as_ref().send(Operation::SetSkeleton(skeleton));
    }
}

impl DynamicMesh {
    /// Returns the number of vertices of the geometry base shape.
    pub fn vertex_count(&self) -> usize {
        self.geometry.base.vertices.len()
    }

    /// Set mesh material.
    pub fn set_material<M: Into<Material>>(
        &mut self,
        material: M,
    ) {
        self.as_ref().send(Operation::SetMaterial(material.into()));
    }
}
<|endoftext|>


<commit_before>//! A module of helper traits and iterators that are not intended to be used
//! directly.

use std::ops::{
    RangeFull,
    Range,
    RangeTo,
    RangeFrom
};

use std::mem;
use std::slice;

/// Apply `IntoIterator` on each element of a tuple.
pub trait IntoIteratorTuple
{
    /// Tuple of values that implement `Iterator`.
    type Output;

    /// Return a tuple of iterators.
    fn into_iterator_tuple(self) -> Self::Output;
}

/// A helper trait for (x, y, z) ++ w => (x, y, z, w),
/// used for implementing `iproduct!`.
pub trait AppendTuple<X> {
    /// Resulting tuple type
    type Result;
    /// “Append” value `x` to a tuple.
    fn append(self, x: X) -> Self::Result;
}

macro_rules! impl_append_tuple(
    () => (
        impl<T> AppendTuple<T> for () {
            type Result = (T, );
            fn append(self, x: T) -> (T, ) {
                (x, )
            }
        }
    );

    ($A:ident, $($B:ident,)*) => (
        impl_append_tuple!($($B,)*);
        #[allow(non_snake_case)]
        impl<$A, $($B,)* T> AppendTuple<T> for ($A, $($B),*) {
            type Result = ($A, $($B, )* T);
            fn append(self, x: T) -> ($A, $($B,)* T) {
                let ($A, $($B),*) = self;
                ($A, $($B,)* x)
            }
        }
    );
);

impl_append_tuple!(A, B, C, D, E, F, G, H, I, J, K, L,);

/// A helper iterator that maps an iterator of tuples like
/// `((A, B), C)` to an iterator of `(A, B, C)`.
///
/// Used by the `iproduct!()` macro.
#[derive(Clone)]
pub struct FlatTuples<I> {
    iter: I,
}

impl<I> FlatTuples<I> {
    /// Create a new `FlatTuples`.
    #[doc(hidden)]
    pub fn new(iter: I) -> Self {
        FlatTuples { iter: iter }
    }
}

impl<X, T, I> Iterator for FlatTuples<I>
    where I: Iterator<Item = (T, X)>,
          T: AppendTuple<X>
{
    type Item = T::Result;
    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(t, x)| t.append(x))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<X, T, I> DoubleEndedIterator for FlatTuples<I>
    where I: DoubleEndedIterator<Item = (T, X)>,
          T: AppendTuple<X>
{
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter.next_back().map(|(t, x)| t.append(x))
    }
}

/// A trait for items that can *maybe* be joined together.
pub trait MendSlice
{
    #[doc(hidden)]
    /// If the slices are contiguous, return them joined into one.
    fn mend(Self, Self) -> Result<Self, (Self, Self)>
        where Self: Sized;
}

impl<'a, T> MendSlice for &'a [T] {
    #[inline]
    fn mend(a: Self, b: Self) -> Result<Self, (Self, Self)> {
        unsafe {
            let a_end = a.as_ptr().offset(a.len() as isize);
            if a_end == b.as_ptr() {
                Ok(slice::from_raw_parts(a.as_ptr(), a.len() + b.len()))
            } else {
                Err((a, b))
            }
        }
    }
}

impl<'a, T> MendSlice for &'a mut [T] {
    #[inline]
    fn mend(a: Self, b: Self) -> Result<Self, (Self, Self)> {
        unsafe {
            let a_end = a.as_ptr().offset(a.len() as isize);
            if a_end == b.as_ptr() {
                Ok(slice::from_raw_parts_mut(a.as_mut_ptr(), a.len() + b.len()))
            } else {
                Err((a, b))
            }
        }
    }
}

impl<'a> MendSlice for &'a str {
    #[inline]
    fn mend(a: Self, b: Self) -> Result<Self, (Self, Self)> {
        unsafe { mem::transmute(MendSlice::mend(a.as_bytes(), b.as_bytes())) }
    }
}

<commit_msg>Rm unused imports in misc<commit_after>//! A module of helper traits and iterators that are not intended to be used
//! directly.

use std::mem;
use std::slice;

/// Apply `IntoIterator` on each element of a tuple.
pub trait IntoIteratorTuple
{
    /// Tuple of values that implement `Iterator`.
    type Output;

    /// Return a tuple of iterators.
    fn into_iterator_tuple(self) -> Self::Output;
}

/// A helper trait for (x, y, z) ++ w => (x, y, z, w),
/// used for implementing `iproduct!`.
pub trait AppendTuple<X> {
    /// Resulting tuple type
    type Result;
    /// “Append” value `x` to a tuple.
    fn append(self, x: X) -> Self::Result;
}

macro_rules! impl_append_tuple(
    () => (
        impl<T> AppendTuple<T> for () {
            type Result = (T, );
            fn append(self, x: T) -> (T, ) {
                (x, )
            }
        }
    );

    ($A:ident, $($B:ident,)*) => (
        impl_append_tuple!($($B,)*);
        #[allow(non_snake_case)]
        impl<$A, $($B,)* T> AppendTuple<T> for ($A, $($B),*) {
            type Result = ($A, $($B, )* T);
            fn append(self, x: T) -> ($A, $($B,)* T) {
                let ($A, $($B),*) = self;
                ($A, $($B,)* x)
            }
        }
    );
);

impl_append_tuple!(A, B, C, D, E, F, G, H, I, J, K, L,);

/// A helper iterator that maps an iterator of tuples like
/// `((A, B), C)` to an iterator of `(A, B, C)`.
///
/// Used by the `iproduct!()` macro.
#[derive(Clone)]
pub struct FlatTuples<I> {
    iter: I,
}

impl<I> FlatTuples<I> {
    /// Create a new `FlatTuples`.
    #[doc(hidden)]
    pub fn new(iter: I) -> Self {
        FlatTuples { iter: iter }
    }
}

impl<X, T, I> Iterator for FlatTuples<I>
    where I: Iterator<Item = (T, X)>,
          T: AppendTuple<X>
{
    type Item = T::Result;
    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(t, x)| t.append(x))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<X, T, I> DoubleEndedIterator for FlatTuples<I>
    where I: DoubleEndedIterator<Item = (T, X)>,
          T: AppendTuple<X>
{
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter.next_back().map(|(t, x)| t.append(x))
    }
}

/// A trait for items that can *maybe* be joined together.
pub trait MendSlice
{
    #[doc(hidden)]
    /// If the slices are contiguous, return them joined into one.
    fn mend(Self, Self) -> Result<Self, (Self, Self)>
        where Self: Sized;
}

impl<'a, T> MendSlice for &'a [T] {
    #[inline]
    fn mend(a: Self, b: Self) -> Result<Self, (Self, Self)> {
        unsafe {
            let a_end = a.as_ptr().offset(a.len() as isize);
            if a_end == b.as_ptr() {
                Ok(slice::from_raw_parts(a.as_ptr(), a.len() + b.len()))
            } else {
                Err((a, b))
            }
        }
    }
}

impl<'a, T> MendSlice for &'a mut [T] {
    #[inline]
    fn mend(a: Self, b: Self) -> Result<Self, (Self, Self)> {
        unsafe {
            let a_end = a.as_ptr().offset(a.len() as isize);
            if a_end == b.as_ptr() {
                Ok(slice::from_raw_parts_mut(a.as_mut_ptr(), a.len() + b.len()))
            } else {
                Err((a, b))
            }
        }
    }
}

impl<'a> MendSlice for &'a str {
    #[inline]
    fn mend(a: Self, b: Self) -> Result<Self, (Self, Self)> {
        unsafe { mem::transmute(MendSlice::mend(a.as_bytes(), b.as_bytes())) }
    }
}

<|endoftext|>


<commit_before>#![cfg_attr(feature = "deny-warnings", deny(warnings))]

use rustc_tools_util::VersionInfo;

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"#;

fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

fn show_version() {
    let version_info = rustc_tools_util::get_version_info!();
    println!("{}", version_info);
}

pub fn main() {
    // Check for version and help flags even when invoked as 'cargo-clippy'
    if std::env::args().any(|a| a == "--help" || a == "-h") {
        show_help();
        return;
    }

    if std::env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    if let Err(code) = process(std::env::args().skip(2)) {
        std::process::exit(code);
    }
}

fn process<I>(mut old_args: I) -> Result<(), i32>
where
    I: Iterator<Item = String>,
{
    let mut args = vec!["check".to_owned()];

    for arg in old_args.by_ref() {
        if arg == "--fix" {
            args[0] = "fix".to_owned();
            continue;
        }

        if arg == "--" {
            break;
        }
        args.push(arg);
    }

    let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect();

    let mut path = std::env::current_exe()
        .expect("current executable path invalid")
        .with_file_name("clippy-driver");
    if cfg!(windows) {
        path.set_extension("exe");
    }

    let target_dir = std::env::var_os("CLIPPY_DOGFOOD")
        .map(|_| {
            std::env::var_os("CARGO_MANIFEST_DIR").map_or_else(
                || std::ffi::OsString::from("clippy_dogfood"),
                |d| {
                    std::path::PathBuf::from(d)
                        .join("target")
                        .join("dogfood")
                        .into_os_string()
                },
            )
        })
        .map(|p| ("CARGO_TARGET_DIR", p));

    // Run the dogfood tests directly on nightly cargo. This is required due
    // to a bug in rustup.rs when running cargo on custom toolchains. See issue #3118.
    if std::env::var_os("CLIPPY_DOGFOOD").is_some() && cfg!(windows) {
        args.insert(0, "+nightly".to_string());
    }

    let exit_status = std::process::Command::new("cargo")
        .args(&args)
        .env("RUSTC_WORKSPACE_WRAPPER", path)
        .env("CLIPPY_ARGS", clippy_args)
        .envs(target_dir)
        .spawn()
        .expect("could not run cargo")
        .wait()
        .expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}
<commit_msg>check for unstable options<commit_after>#![cfg_attr(feature = "deny-warnings", deny(warnings))]

use rustc_tools_util::VersionInfo;

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"#;

fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

fn show_version() {
    let version_info = rustc_tools_util::get_version_info!();
    println!("{}", version_info);
}

pub fn main() {
    // Check for version and help flags even when invoked as 'cargo-clippy'
    if std::env::args().any(|a| a == "--help" || a == "-h") {
        show_help();
        return;
    }

    if std::env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    if let Err(code) = process(std::env::args().skip(2)) {
        std::process::exit(code);
    }
}

fn process<I>(mut old_args: I) -> Result<(), i32>
where
    I: Iterator<Item = String>,
{
    let mut args = vec!["check".to_owned()];

    let mut fix = false;
    let mut unstable_options = false;

    for arg in old_args.by_ref() {
        match arg {
            "--fix" => {
                fix = true;
                continue;
            },
            "--" => break,
            // Cover -Zunstable-options and -Z unstable-options
            s if s.ends_with("unstable-options") => unstable_options = true,
            _ => {},
        }

        args.push(arg);
    }

    if fix && !unstable_options {
        panic!("Usage of `--fix` requires `-Z unstable-options`");
    } else {
        args[0] = "fix".to_owned();
    }

    let env_name = if unstable_options {
        "RUSTC_WORKSPACE_WRAPPER"
    } else {
        "RUSTC_WRAPPER"
    };

    let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect();

    let mut path = std::env::current_exe()
        .expect("current executable path invalid")
        .with_file_name("clippy-driver");
    if cfg!(windows) {
        path.set_extension("exe");
    }

    let target_dir = std::env::var_os("CLIPPY_DOGFOOD")
        .map(|_| {
            std::env::var_os("CARGO_MANIFEST_DIR").map_or_else(
                || std::ffi::OsString::from("clippy_dogfood"),
                |d| {
                    std::path::PathBuf::from(d)
                        .join("target")
                        .join("dogfood")
                        .into_os_string()
                },
            )
        })
        .map(|p| ("CARGO_TARGET_DIR", p));

    // Run the dogfood tests directly on nightly cargo. This is required due
    // to a bug in rustup.rs when running cargo on custom toolchains. See issue #3118.
    if std::env::var_os("CLIPPY_DOGFOOD").is_some() && cfg!(windows) {
        args.insert(0, "+nightly".to_string());
    }

    let exit_status = std::process::Command::new("cargo")
        .args(&args)
        .env("RUSTC_WORKSPACE_WRAPPER", path)
        .env("CLIPPY_ARGS", clippy_args)
        .envs(target_dir)
        .spawn()
        .expect("could not run cargo")
        .wait()
        .expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;

#[derive(Debug, PartialEq, Clone)]
enum Token {
    Unknown(String), // Invalid test (basically non-ascii)
    Literal(String), // Numeric literal number
    Func(Function), // Pre-defined function (like cos() )
    Const(Constant), // Constant like pi or e
    Var(String), // str arbitrary single char variable name
    Op(Operator), // Any of the 4 operators (+-*/)
    Open, // Open parens '('
    Close, // Closing parens ')'
    Set(Vec<Token>), // [ (, tokens..., ) ]
    Fake,
}

#[derive(Debug, PartialEq, Clone)]
enum Function {
    Sqrt(Vec<Token>),
    Ln(Vec<Token>),
    Log(f64, Vec<Token>),
    Sin(Vec<Token>),
    Cos(Vec<Token>),
    Tan(Vec<Token>),
    Asin(Vec<Token>),
    Acos(Vec<Token>),
    Atan(Vec<Token>),
    Sinh(Vec<Token>),
    Cosh(Vec<Token>),
    Tanh(Vec<Token>),
    Asinh(Vec<Token>),
    Acosh(Vec<Token>),
    Atanh(Vec<Token>),
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Constant {
	Pi,
	E,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Operator {
    Add,
    Sub,
    Div,
    Mul,
    Pow,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
enum Assoc {
    Left,
    Right,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
enum Order {
    AddSub = 1,
    MulDiv = 2,
    IMul = 3, // Implicit multiplication
    Pow = 4,
    Paren = 5,
}

#[derive(Debug, PartialEq, Clone)]
struct Expression {
    tokens: Vec<Token>,
    constant: f64,
}

impl Expression {
	fn new(tokens: Vec<Token>, constant: f64) -> Self {
		Expression {tokens: tokens, constant: constant}
	}

	fn push(&mut self, token: Token) {
		self.tokens.push(token);
	}

	fn update_constant(&mut self, constant: &f64) {
		self.constant += *constant;
	}

	fn get_constant(&self) -> f64 {
		self.constant
	}

	fn get_tokens(&self) -> &[Token] {
		self.tokens.as_slice()
	}

	fn get_mut_tokens(&mut self) -> &mut [Token] {
		self.tokens.as_mut_slice()
	}

	fn replace_token(&mut self, index: usize, newToken: Token) {
		self.tokens.remove(index);
		self.tokens.insert(index, newToken);
	}

	fn replace_all_tokens(&mut self, newTokens: Vec<Token>) {
		self.tokens = newTokens
	}

	fn find_first(&self, token: &Token) -> Option<usize> {
		let mut index: usize = 0;
		for t in &self.tokens {
			if t == token {
				return Some(index);
			}
			index += 1;
		}
		None
	}

	fn find_last(&self, token: &Token) -> Option<usize> {
		let mut index: usize = 0;
		let mut found = false;
		for i in (0..self.tokens.len()).rev() {
			if self.tokens.get(i).unwrap() == token {
				index = i;
				return Some(index);
			}
		}
		None
	}

	fn split_at(&self, index: usize) -> (&[Token], &[Token]) {
		self.tokens.split_at(index)
	}

	fn len(&self) -> usize {
		self.tokens.len()
	}
}

fn main() {
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let mut input = String::new();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
    	input.clear();
    	print!(">>>> ");
    	stdout.flush().ok();
        stdin.read_line(&mut input).unwrap();
        input = strip_white_space(&input);
        input = input.to_lowercase();
        if input == "quit" {
        	print!("Exiting...");
        	break;
        }
        let mut expr = parse_input(&input).unwrap();
        println!("{:?}", &expr);
    }
}

fn strip_white_space(input: &String) -> String {
	input.split_whitespace().collect::<Vec<&str>>().join("")
}

fn parse_input(input: &String) -> Result<Expression, ()> {
	let mut expr: Expression = Expression::new(Vec::new(), 0.0);
	let mut builder: Vec<Token> = Vec::new();
	for c in input.chars() {
		match c {
			'-' => {
				expr.push(Token::Op(Operator::Sub));
			},
			'+' => {
				expr.push(Token::Op(Operator::Add));
			},
			'/' => {
				expr.push(Token::Op(Operator::Div));
			},
			'*' => {
				expr.push(Token::Op(Operator::Mul));
			},
			'^' => {
				expr.push(Token::Op(Operator::Pow));
			},
			'(' => {
				expr.push(Token::Open);
			},
			')' => {
				expr.push(Token::Close);
			},
			_ => continue,
		}
	}
	if let Some(index) = expr.find_first(&Token::Open) { // If we find an index of an Open
		let endSet: usize = expr.find_last(&Token::Close).unwrap();
		let mut lhs: Vec<Token> = Vec::new();
		let mut rhs: Vec<Token> = Vec::new();
		{
			let (temp_lhs, temp_rhs) = expr.split_at(index); // [0, where set should be placed)
			lhs = temp_lhs.to_vec();
			rhs = temp_rhs.to_vec(); // [where set should be placed, len)
			rhs.remove(0);
			// split rhs at endset - 2
			// Left part gets pushed as a Set to lhs
			// Remove index 0 of right part (this is the close we split on) and add that as a vector to lhs
			let (mut left_rhs, mut right_rhs) = rhs.split_at(endSet-2);
			let (mut left_rhs, mut right_rhs) = (left_rhs.to_vec(), right_rhs.to_vec());
			right_rhs.remove(0);
			//rhs.remove(endSet-2); // Sub one because we removed the first element, need to split at endSet -2
			lhs.push(Token::Set(left_rhs));
			lhs.append(&mut right_rhs);
		}
		for i in (0..lhs.len()).rev() {
			if lhs.get(i).unwrap() == &Token::Close {
				lhs.remove(i);
				break;
			}
		}
		expr.replace_all_tokens(lhs);
	}
	Ok(expr)
}<commit_msg>Unused variable<commit_after>use std::io;
use std::io::Write;

#[derive(Debug, PartialEq, Clone)]
enum Token {
    Unknown(String), // Invalid test (basically non-ascii)
    Literal(String), // Numeric literal number
    Func(Function), // Pre-defined function (like cos() )
    Const(Constant), // Constant like pi or e
    Var(String), // str arbitrary single char variable name
    Op(Operator), // Any of the 4 operators (+-*/)
    Open, // Open parens '('
    Close, // Closing parens ')'
    Set(Vec<Token>), // [ (, tokens..., ) ]
    Fake,
}

#[derive(Debug, PartialEq, Clone)]
enum Function {
    Sqrt(Vec<Token>),
    Ln(Vec<Token>),
    Log(f64, Vec<Token>),
    Sin(Vec<Token>),
    Cos(Vec<Token>),
    Tan(Vec<Token>),
    Asin(Vec<Token>),
    Acos(Vec<Token>),
    Atan(Vec<Token>),
    Sinh(Vec<Token>),
    Cosh(Vec<Token>),
    Tanh(Vec<Token>),
    Asinh(Vec<Token>),
    Acosh(Vec<Token>),
    Atanh(Vec<Token>),
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Constant {
	Pi,
	E,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Operator {
    Add,
    Sub,
    Div,
    Mul,
    Pow,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
enum Assoc {
    Left,
    Right,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
enum Order {
    AddSub = 1,
    MulDiv = 2,
    IMul = 3, // Implicit multiplication
    Pow = 4,
    Paren = 5,
}

#[derive(Debug, PartialEq, Clone)]
struct Expression {
    tokens: Vec<Token>,
    constant: f64,
}

impl Expression {
	fn new(tokens: Vec<Token>, constant: f64) -> Self {
		Expression {tokens: tokens, constant: constant}
	}

	fn push(&mut self, token: Token) {
		self.tokens.push(token);
	}

	fn update_constant(&mut self, constant: &f64) {
		self.constant += *constant;
	}

	fn get_constant(&self) -> f64 {
		self.constant
	}

	fn get_tokens(&self) -> &[Token] {
		self.tokens.as_slice()
	}

	fn get_mut_tokens(&mut self) -> &mut [Token] {
		self.tokens.as_mut_slice()
	}

	fn replace_token(&mut self, index: usize, newToken: Token) {
		self.tokens.remove(index);
		self.tokens.insert(index, newToken);
	}

	fn replace_all_tokens(&mut self, newTokens: Vec<Token>) {
		self.tokens = newTokens
	}

	fn find_first(&self, token: &Token) -> Option<usize> {
		let mut index: usize = 0;
		for t in &self.tokens {
			if t == token {
				return Some(index);
			}
			index += 1;
		}
		None
	}

	fn find_last(&self, token: &Token) -> Option<usize> {
		let mut index: usize = 0;
		let mut found = false;
		for i in (0..self.tokens.len()).rev() {
			if self.tokens.get(i).unwrap() == token {
				index = i;
				return Some(index);
			}
		}
		None
	}

	fn split_at(&self, index: usize) -> (&[Token], &[Token]) {
		self.tokens.split_at(index)
	}

	fn len(&self) -> usize {
		self.tokens.len()
	}
}

fn main() {
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let mut input = String::new();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
    	input.clear();
    	print!(">>>> ");
    	stdout.flush().ok();
        stdin.read_line(&mut input).unwrap();
        input = strip_white_space(&input);
        input = input.to_lowercase();
        if input == "quit" {
        	print!("Exiting...");
        	break;
        }
        let mut expr = parse_input(&input).unwrap();
        println!("{:?}", &expr);
    }
}

fn strip_white_space(input: &String) -> String {
	input.split_whitespace().collect::<Vec<&str>>().join("")
}

fn parse_input(input: &String) -> Result<Expression, ()> {
	let mut expr: Expression = Expression::new(Vec::new(), 0.0);
	for c in input.chars() {
		match c {
			'-' => {
				expr.push(Token::Op(Operator::Sub));
			},
			'+' => {
				expr.push(Token::Op(Operator::Add));
			},
			'/' => {
				expr.push(Token::Op(Operator::Div));
			},
			'*' => {
				expr.push(Token::Op(Operator::Mul));
			},
			'^' => {
				expr.push(Token::Op(Operator::Pow));
			},
			'(' => {
				expr.push(Token::Open);
			},
			')' => {
				expr.push(Token::Close);
			},
			_ => continue,
		}
	}
	if let Some(index) = expr.find_first(&Token::Open) { // If we find an index of an Open
		let endSet: usize = expr.find_last(&Token::Close).unwrap();
		let mut lhs: Vec<Token> = Vec::new();
		let mut rhs: Vec<Token> = Vec::new();
		{
			let (temp_lhs, temp_rhs) = expr.split_at(index); // [0, where set should be placed)
			lhs = temp_lhs.to_vec();
			rhs = temp_rhs.to_vec(); // [where set should be placed, len)
			rhs.remove(0);
			// split rhs at endset - 2
			// Left part gets pushed as a Set to lhs
			// Remove index 0 of right part (this is the close we split on) and add that as a vector to lhs
			let (mut left_rhs, mut right_rhs) = rhs.split_at(endSet-2);
			let (mut left_rhs, mut right_rhs) = (left_rhs.to_vec(), right_rhs.to_vec());
			right_rhs.remove(0);
			//rhs.remove(endSet-2); // Sub one because we removed the first element, need to split at endSet -2
			lhs.push(Token::Set(left_rhs));
			lhs.append(&mut right_rhs);
		}
		for i in (0..lhs.len()).rev() {
			if lhs.get(i).unwrap() == &Token::Close {
				lhs.remove(i);
				break;
			}
		}
		expr.replace_all_tokens(lhs);
	}
	Ok(expr)
}<|endoftext|>


<commit_before>use std::env;
use std::fmt;

extern crate syn;
use syn::*;

mod rust_lib;

#[derive(Debug)]
struct ConvertedType {
    /// The type converted to C (e.g. `uint32_t`)
    prefix: String,
    /// Stuff that might need to go after the identifier (e.g. `[3]` for an array).
    postfix: String,
}

impl ConvertedType {
    fn new<T: Into<String>>(pre: T, post: String) -> Self {
        ConvertedType {
            prefix: pre.into(),
            postfix: post
        }
    }
}

impl Into<String> for ConvertedType {
    fn into(self) -> String {
        let mut str = String::from(self.prefix);
        str.push_str(&self.postfix);
        str
    }
}

impl From<String> for ConvertedType {
    fn from(str: String) -> ConvertedType {
        ConvertedType {
            prefix: str,
            postfix: String::new()
        }
    }
}

impl fmt::Display for ConvertedType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{}", &self.prefix, &self.postfix)
    }
}

fn has_attribute(target: MetaItem, attrs: &Vec<Attribute>) -> bool {
    return attrs
               .iter()
               .any(|ref attr| attr.style == AttrStyle::Outer && attr.value == target);
}

fn has_no_mangle(attrs: &Vec<Attribute>) -> bool {
    has_attribute(MetaItem::Word(Ident::new("no_mangle")), attrs)
}

fn wr_func_body(attrs: &Vec<Attribute>) -> String {
    if has_attribute(MetaItem::Word(Ident::new("destructor_safe")), attrs) {
        String::from("WR_DESTRUCTOR_SAFE_FUNC")
    } else {
        String::from("WR_FUNC")
    }
}

fn is_repr_c(attrs: &Vec<Attribute>) -> bool {
    let repr_args = vec![NestedMetaItem::MetaItem(MetaItem::Word(Ident::new("C")))];
    has_attribute(MetaItem::List(Ident::new("repr"), repr_args), attrs)
}

fn is_c_abi(abi: &Option<Abi>) -> bool {
    abi == &Some(Abi::Named(String::from("C")))
}

fn map_path(p: &Path) -> String {
    let l = p.segments[0].ident.to_string();
    let mut c = match l.as_ref() {
        "usize" => "size_t".to_string(),
        "u8" => "uint8_t".to_string(),
        "u32" => "uint32_t".to_string(),
        "u64" => "uint64_t".to_string(),
        "i8" => "int8_t".to_string(),
        "i32" => "int32_t".to_string(),
        "i64" => "int64_t".to_string(),
        "f32" => "float".to_string(),
        "c_void" => "void".to_string(),
        _ => l,
    };
    if let PathParameters::AngleBracketed(ref d) = p.segments[0].parameters {
        let template_args = d.types
            .iter()
            .map(|ty| map_ty(ty).into())
            .collect::<Vec<String>>()
            .join(", ");
        if !template_args.is_empty() {
            c.push('<');
            c.push_str(&template_args);
            c.push('>');
        }
    }
    c
}

fn map_mut_ty(mut_ty: &MutTy) -> ConvertedType {
    map_ty(&mut_ty.ty)
}

fn map_ty(ty: &Ty) -> ConvertedType {
    match ty {
        &Ty::Path(_, ref p) => ConvertedType::from(map_path(p)),
        &Ty::Ptr(ref p) => ConvertedType::from(format!("{}*", map_ty(&p.ty))),
        &Ty::Rptr(_, ref mut_ty) => ConvertedType::from(format!("{}*", map_mut_ty(mut_ty))),
        &Ty::Array(ref p, ConstExpr::Lit(Lit::Int(sz, _))) => ConvertedType::new(map_ty(&p), format!("[{}]", sz)),
        _ => ConvertedType::from(format!("unknown {:?}", ty)),
    }
}

fn map_return_type(ret: &FunctionRetTy) -> String {
    match ret {
        &FunctionRetTy::Default => "void".to_string(),
        &FunctionRetTy::Ty(ref ty) => map_ty(ty).into(),
    }
}

fn map_pat(pat: &Pat) -> String {
    match pat {
        &Pat::Ident(_, ref ident, _) => ident.to_string(),
        _ => format!("unknown {:?}", pat),
    }

}

fn map_arg(f: &FnArg) -> String {
    match f {
        &FnArg::Captured(ref pat, ref ty) => format!("{} {}", map_ty(ty), map_pat(pat)),
        _ => "unknown".to_string(),
    }
}

fn map_field(f: &Field) -> String {
    let mut ret = String::from("  ");
    let converted = map_ty(&f.ty);
    ret.push_str(&converted.prefix);
    ret.push(' ');
    ret.push_str(&f.ident.as_ref().expect("Struct fields must have idents").to_string());
    ret.push_str(&converted.postfix);
    ret.push_str(";\n");
    ret
}

fn map_generic_param(t: &TyParam) -> String {
    let mut ret = String::from("typename ");
    ret.push_str(&t.ident.to_string());
    ret
}

fn main() {
    let p = env::args().nth(1).unwrap();

    rust_lib::parse(p, &|_, items| {
        for item in items {
            match item.node {
                ItemKind::Fn(ref decl,
                             ref _unsafe,
                             ref _const,
                             ref abi,
                             ref _generic,
                             ref _block) => {
                    if has_no_mangle(&item.attrs) && is_c_abi(&abi) {
                        println!("WR_INLINE {}\n{}({})\n{};\n",
                                 map_return_type(&decl.output),
                                 item.ident,
                                 decl.inputs
                                     .iter()
                                     .map(map_arg)
                                     .collect::<Vec<_>>()
                                     .join(", "),
                                 wr_func_body(&item.attrs));
                    }
                }
                ItemKind::Struct(ref variant,
                                 ref generics) => {
                    if is_repr_c(&item.attrs) {
                        if !generics.ty_params.is_empty() {
                            println!("template<{}>",
                                     generics.ty_params
                                         .iter()
                                         .map(map_generic_param)
                                         .collect::<Vec<_>>()
                                         .join(", "));
                        }
                        if let &VariantData::Struct(ref fields) = variant {
                            println!("struct {} {{\n{}}};\n",
                                     item.ident,
                                     fields
                                         .iter()
                                         .map(map_field)
                                         .collect::<String>());
                        }
                    }
                }
                _ => {}
            }
        }
    });
}
<commit_msg>Add conversion of enums<commit_after>use std::env;
use std::fmt;
use std::io;
use std::io::Write;

extern crate syn;
use syn::*;

mod rust_lib;

#[derive(Debug)]
struct ConvertedType {
    /// The type converted to C (e.g. `uint32_t`)
    prefix: String,
    /// Stuff that might need to go after the identifier (e.g. `[3]` for an array).
    postfix: String,
}

impl ConvertedType {
    fn new<T: Into<String>>(pre: T, post: String) -> Self {
        ConvertedType {
            prefix: pre.into(),
            postfix: post
        }
    }
}

impl Into<String> for ConvertedType {
    fn into(self) -> String {
        let mut str = String::from(self.prefix);
        str.push_str(&self.postfix);
        str
    }
}

impl From<String> for ConvertedType {
    fn from(str: String) -> ConvertedType {
        ConvertedType {
            prefix: str,
            postfix: String::new()
        }
    }
}

impl fmt::Display for ConvertedType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{}", &self.prefix, &self.postfix)
    }
}

fn has_attribute(target: MetaItem, attrs: &Vec<Attribute>) -> bool {
    return attrs
               .iter()
               .any(|ref attr| attr.style == AttrStyle::Outer && attr.value == target);
}

fn has_no_mangle(attrs: &Vec<Attribute>) -> bool {
    has_attribute(MetaItem::Word(Ident::new("no_mangle")), attrs)
}

fn wr_func_body(attrs: &Vec<Attribute>) -> String {
    if has_attribute(MetaItem::Word(Ident::new("destructor_safe")), attrs) {
        String::from("WR_DESTRUCTOR_SAFE_FUNC")
    } else {
        String::from("WR_FUNC")
    }
}

fn is_repr_c(attrs: &Vec<Attribute>) -> bool {
    let repr_args = vec![NestedMetaItem::MetaItem(MetaItem::Word(Ident::new("C")))];
    has_attribute(MetaItem::List(Ident::new("repr"), repr_args), attrs)
}

fn is_repr_u32(attrs: &Vec<Attribute>) -> bool {
    let repr_args = vec![NestedMetaItem::MetaItem(MetaItem::Word(Ident::new("u32")))];
    has_attribute(MetaItem::List(Ident::new("repr"), repr_args), attrs)
}

fn is_c_abi(abi: &Option<Abi>) -> bool {
    abi == &Some(Abi::Named(String::from("C")))
}

fn map_path(p: &Path) -> String {
    let l = p.segments[0].ident.to_string();
    let mut c = match l.as_ref() {
        "usize" => "size_t".to_string(),
        "u8" => "uint8_t".to_string(),
        "u32" => "uint32_t".to_string(),
        "u64" => "uint64_t".to_string(),
        "i8" => "int8_t".to_string(),
        "i32" => "int32_t".to_string(),
        "i64" => "int64_t".to_string(),
        "f32" => "float".to_string(),
        "c_void" => "void".to_string(),
        _ => l,
    };
    if let PathParameters::AngleBracketed(ref d) = p.segments[0].parameters {
        let template_args = d.types
            .iter()
            .map(|ty| map_ty(ty).into())
            .collect::<Vec<String>>()
            .join(", ");
        if !template_args.is_empty() {
            c.push('<');
            c.push_str(&template_args);
            c.push('>');
        }
    }
    c
}

fn map_mut_ty(mut_ty: &MutTy) -> ConvertedType {
    map_ty(&mut_ty.ty)
}

fn map_ty(ty: &Ty) -> ConvertedType {
    match ty {
        &Ty::Path(_, ref p) => ConvertedType::from(map_path(p)),
        &Ty::Ptr(ref p) => ConvertedType::from(format!("{}*", map_ty(&p.ty))),
        &Ty::Rptr(_, ref mut_ty) => ConvertedType::from(format!("{}*", map_mut_ty(mut_ty))),
        &Ty::Array(ref p, ConstExpr::Lit(Lit::Int(sz, _))) => ConvertedType::new(map_ty(&p), format!("[{}]", sz)),
        _ => ConvertedType::from(format!("unknown {:?}", ty)),
    }
}

fn map_return_type(ret: &FunctionRetTy) -> String {
    match ret {
        &FunctionRetTy::Default => "void".to_string(),
        &FunctionRetTy::Ty(ref ty) => map_ty(ty).into(),
    }
}

fn map_pat(pat: &Pat) -> String {
    match pat {
        &Pat::Ident(_, ref ident, _) => ident.to_string(),
        _ => format!("unknown {:?}", pat),
    }

}

fn map_arg(f: &FnArg) -> String {
    match f {
        &FnArg::Captured(ref pat, ref ty) => format!("{} {}", map_ty(ty), map_pat(pat)),
        _ => "unknown".to_string(),
    }
}

fn map_field(f: &Field) -> String {
    let mut ret = String::from("  ");
    let converted = map_ty(&f.ty);
    ret.push_str(&converted.prefix);
    ret.push(' ');
    ret.push_str(&f.ident.as_ref().expect("Struct fields must have idents").to_string());
    ret.push_str(&converted.postfix);
    ret.push_str(";\n");
    ret
}

fn map_generic_param(t: &TyParam) -> String {
    let mut ret = String::from("typename ");
    ret.push_str(&t.ident.to_string());
    ret
}

fn fold_enum_variants(accum: (String, i32), v: &Variant) -> (String, i32) {
    // `accum` contains the combined string of converted enum variants so far, to which
    // we will append the converted version of `v`. The other thing in `accum` is the
    // value of the previous variant. If `v` has an explicit value we keep that, otherwise
    // we increment the value of the previous variant to get the new one. This is all
    // so that we properly support enums with explicitly-specified and discontinuous
    // values.
    let mut ret = accum.0;
    ret.push_str("  ");
    ret.push_str(&v.ident.to_string());
    ret.push_str(" = ");
    let new_value = match &v.discriminant {
        &None => accum.1 + 1,
        &Some(ConstExpr::Lit(Lit::Int(ref specified_value, _))) => *specified_value as i32,
        &Some(_) => {
            // we don't handle this yet, so just put in something that will fail C compilation
            writeln!(io::stderr(), "warning, unsupported enum discriminant").unwrap();
            ret.push_str("???");
            accum.1 + 1
        }
    };
    ret.push_str(&new_value.to_string());
    ret.push_str(",\n");
    (ret, new_value)
}

fn main() {
    let p = env::args().nth(1).unwrap();

    rust_lib::parse(p, &|mod_name, items| {
        for item in items {
            match item.node {
                ItemKind::Fn(ref decl,
                             ref _unsafe,
                             ref _const,
                             ref abi,
                             ref _generic,
                             ref _block) => {
                    writeln!(io::stderr(), "processing function {}::{}", mod_name, &item.ident).unwrap();
                    if has_no_mangle(&item.attrs) && is_c_abi(&abi) {
                        println!("WR_INLINE {}\n{}({})\n{};\n",
                                 map_return_type(&decl.output),
                                 item.ident,
                                 decl.inputs
                                     .iter()
                                     .map(map_arg)
                                     .collect::<Vec<_>>()
                                     .join(", "),
                                 wr_func_body(&item.attrs));
                    }
                }
                ItemKind::Struct(ref variant,
                                 ref generics) => {
                    writeln!(io::stderr(), "processing struct {}::{}", mod_name, &item.ident).unwrap();
                    if is_repr_c(&item.attrs) {
                        if !generics.ty_params.is_empty() {
                            println!("template<{}>",
                                     generics.ty_params
                                         .iter()
                                         .map(map_generic_param)
                                         .collect::<Vec<_>>()
                                         .join(", "));
                        }
                        if let &VariantData::Struct(ref fields) = variant {
                            println!("struct {} {{\n{}}};\n",
                                     item.ident,
                                     fields
                                         .iter()
                                         .map(map_field)
                                         .collect::<String>());
                        }
                    }
                }
                ItemKind::Enum(ref variants, ref _generics) => {
                    writeln!(io::stderr(), "processing enum {}::{}", mod_name, &item.ident).unwrap();
                    if is_repr_u32(&item.attrs) {
                        println!("enum class {}: uint32_t {{\n{}\n  Sentinel /* this must be last for serialization purposes. */\n}};\n",
                                 item.ident,
                                 variants
                                     .iter()
                                     .fold((String::new(), -1), fold_enum_variants)
                                     .0);
                    }
                }
                _ => {}
            }
        }
    });
}
<|endoftext|>


<commit_before>use std::char;
use std::collections::BTreeSet;
use std::io;
use std::process;

const NSQRT: usize = 3;
const N: usize = NSQRT * NSQRT;
const NSQ: usize = N*N;

fn error(msg: String) -> ! {
    println!("error: {}", msg);
    process::exit(1);
}

/// Return the 0-based row index of `cell`.
fn row(cell: usize) -> usize {
    cell / N
}

/// Return the 0-based row index of `cell`.
fn col(cell: usize) -> usize {
    cell % N
}

/// Return the 0-based index of the upper-left cell of `cell`'s group.
fn group(cell: usize) -> usize {
    let r = row(cell);
    let c = col(cell);
    (N * (r - r % NSQRT)) + (c - c % NSQRT)
}

/// Return the neighbors of `cell`:
/// - The cells on the same row;
/// - The cells on the same column;
/// - The same in the same group.
/// Note: `cell` is not a neighbor of itself.
fn neighbors(cell: usize) -> BTreeSet<usize> {
    let mut all_neighbors: BTreeSet<usize> = BTreeSet::new();

    // Neighbors on row
    for col in 0..N {
        all_neighbors.insert((N * row(cell)) + col);
    }

    // Neighbors on column
    for row in 0..N {
        all_neighbors.insert((N * row) + col(cell));
    }

    // Neighbors in group
    let leader = group(cell);
    for r in row(leader) .. row(leader) + NSQRT {
        for c in col(leader) .. col(leader) + NSQRT {
            all_neighbors.insert(N * r + c);
        }
    }

    all_neighbors.remove(&cell);
    return all_neighbors;
}

/// A sudoku board is represented by a vector of bytes.
#[derive(Debug)]
struct SudokuBoard(Vec<u8>);

impl SudokuBoard {
    /// Create a new sudoku board from a string.
    /// A non-zero digit stands for itself,
    /// a dot stands for a blank cell,
    /// anything else is an error.
    fn from_str(digits: &str) -> Self {
        if digits.len() != NSQ {
            error(format!("invalid puzzle length; expected {}, got {}",
                          NSQ, digits.len()));
        }
        let mut v = Vec::with_capacity(NSQ);
        for d in digits.chars() {
            match d {
                '.' => { v.push(0); }
                '1' ... '9' => {
                    let n = d.to_digit(10).unwrap() as u8;
                    v.push(n);
                }
                _ => { error(format!("invalid digit ({:?}) in string", d)); }
            }
        }
        SudokuBoard(v)
    }

    fn to_str(&self) -> String {
        let mut s = String::with_capacity(NSQ);
        for n in self.0.iter() {
            if *n == 0 {
                s.push('.');
            } else {
                s.push(char::from_digit(*n as u32, 10).unwrap());
            }
        }
        s
    }

    /// Convert a sudoku board to a rough string representation.
    fn to_matrix(&self) -> String {
        let mut s = String::with_capacity(N + NSQ);
        let mut i = 0;
        for n in self.0.iter() {
            if i % N == 0 {
                s.push('\n');
            }
            if *n == 0 {
                s.push('.');
            } else {
                s.push(char::from_digit(*n as u32, 10).unwrap());
            }
            i += 1;
        }
        s
    }

    /// A cell is solved if its content is non-zero.
    fn is_solved(&self, cell: usize) -> bool {
        self.0[cell] != 0
    }

    /// Return the list of candidates for a cell.
    /// The candidates are the digits from 1 to NSQ
    /// that are *not* solved in any of `cell`'s neighbors.
    fn candidates(&self, cell: usize) -> BTreeSet<u8> {
        let mut non_candidates = BTreeSet::new();
        for n in neighbors(cell) {
            let x = self.0[n];
            if x != 0 {
                non_candidates.insert(x);
            }
        }
        let mut candidates: BTreeSet<u8> = (1_u8 .. (N+1) as u8).collect();
        for nc in non_candidates {
            candidates.remove(&nc);
        }
        candidates
    }

    /// Solve a sudoku board by backtracking.
    /// Return true if the board is solved, false otherwise.
    fn solve(&mut self, cell: usize) -> bool {
        // If we reach the end of the board (NSQ'th cell),
        // we have solved the board, i.e., put digits into
        // cells without backtracking.
        if cell >= NSQ {
            return true;
        }

        // Skip over already-solved cells (initial solutions)
        if self.is_solved(cell) {
            return self.solve(cell + 1);
        }

        // Try the candidates in order.
        // Loop invariant: self.0[cell] = 0
        // coming into the loop and exiting the loop.
        for c in self.candidates(cell) {
            self.0[cell] = c;
            if self.solve(cell + 1) {
                return true;
            } else {
                self.0[cell] = 0;
            }
        }
        // No candidate satisfied the constraints, backtrack.
        return false;
    }
}

fn main() {
    let stdin = io::stdin();
    let mut buf = String::with_capacity(NSQ);

    loop {
        buf.clear();
        match stdin.read_line(&mut buf) {
            Err(e) => { error(format!("I/O error, {:?}", e)); }
            Ok(0) => { return; }
            Ok(_) => { /* pass through */ }
        }
        let mut sb = SudokuBoard::from_str(&buf.trim());
        let q = sb.solve(0);
        if q {
            println!("{}", sb.to_str());
        } else {
            println!("No solution");
        }
    }
}

#[test]
fn test_row_col() {
    assert_eq!(row(11), 1);
    assert_eq!(col(11), 2);
}

#[test]
fn test_group() {
    assert_eq!(group(0), 0);
    assert_eq!(group(1), 0);
    assert_eq!(group(2), 0);
    assert_eq!(group(9), 0);
    assert_eq!(group(10), 0);
    assert_eq!(group(11), 0);
    assert_eq!(group(18), 0);
    assert_eq!(group(19), 0);
    assert_eq!(group(20), 0);
    assert_eq!(group(60), 60);
    assert_eq!(group(61), 60);
    assert_eq!(group(62), 60);
    assert_eq!(group(69), 60);
    assert_eq!(group(70), 60);
    assert_eq!(group(71), 60);
    assert_eq!(group(78), 60);
    assert_eq!(group(79), 60);
    assert_eq!(group(80), 60);
}

#[test]
fn test_is_solved() {
    let sb = SudokuBoard(vec![0, 1]);
    assert!(!sb.is_solved(0));
    assert!(sb.is_solved(1));
}

#[test]
fn test_neighbors() {
    assert!(!neighbors(0).contains(&0));
    // Neighbors of 0 on the same row
    assert!(neighbors(0).contains(&1));
    assert!(neighbors(0).contains(&2));
    assert!(neighbors(0).contains(&3));
    assert!(neighbors(0).contains(&4));
    assert!(neighbors(0).contains(&5));
    assert!(neighbors(0).contains(&6));
    assert!(neighbors(0).contains(&7));
    assert!(neighbors(0).contains(&8));
    // Neighbors of 0 on the same col
    assert!(neighbors(0).contains(&9));
    assert!(neighbors(0).contains(&18));
    assert!(neighbors(0).contains(&27));
    assert!(neighbors(0).contains(&36));
    assert!(neighbors(0).contains(&45));
    assert!(neighbors(0).contains(&54));
    assert!(neighbors(0).contains(&63));
    assert!(neighbors(0).contains(&72));
    // Neighbors of 0 in the same group
    assert!(neighbors(0).contains(&1));
    assert!(neighbors(0).contains(&2));
    assert!(neighbors(0).contains(&9));
    assert!(neighbors(0).contains(&10));
    assert!(neighbors(0).contains(&11));
    assert!(neighbors(0).contains(&18));
    assert!(neighbors(0).contains(&19));
    assert!(neighbors(0).contains(&20));
}

#[test]
fn test_candidates() {
    let sb = SudokuBoard::from_str(".2......34..........6...................................................5........");
    assert!(!sb.candidates(0).contains(&2));
    assert!(!sb.candidates(0).contains(&3));
    assert!(!sb.candidates(0).contains(&4));
    assert!(!sb.candidates(0).contains(&5));
    assert!(!sb.candidates(0).contains(&6));
    assert!(sb.candidates(0).contains(&1));
    assert!(sb.candidates(0).contains(&7));
    assert!(sb.candidates(0).contains(&8));
    assert!(sb.candidates(0).contains(&9));
}
<commit_msg>Propagate constraints<commit_after>use std::char;
use std::collections::BTreeSet;
use std::io;
use std::process;

const NSQRT: usize = 3;
const N: usize = NSQRT * NSQRT;
const NSQ: usize = N*N;

fn error(msg: String) -> ! {
    println!("error: {}", msg);
    process::exit(1);
}

/// Return the 0-based row index of `cell`.
fn row(cell: usize) -> usize {
    cell / N
}

/// Return the 0-based row index of `cell`.
fn col(cell: usize) -> usize {
    cell % N
}

/// Return the 0-based index of the upper-left cell of `cell`'s group.
fn group(cell: usize) -> usize {
    let r = row(cell);
    let c = col(cell);
    (N * (r - r % NSQRT)) + (c - c % NSQRT)
}

/// Return the neighbors of `cell`:
/// - The cells on the same row;
/// - The cells on the same column;
/// - The same in the same group.
/// Note: `cell` is not a neighbor of itself.
fn neighbors(cell: usize) -> BTreeSet<usize> {
    let mut all_neighbors: BTreeSet<usize> = BTreeSet::new();

    // Neighbors on row
    for col in 0..N {
        all_neighbors.insert((N * row(cell)) + col);
    }

    // Neighbors on column
    for row in 0..N {
        all_neighbors.insert((N * row) + col(cell));
    }

    // Neighbors in group
    let leader = group(cell);
    for r in row(leader) .. row(leader) + NSQRT {
        for c in col(leader) .. col(leader) + NSQRT {
            all_neighbors.insert(N * r + c);
        }
    }

    all_neighbors.remove(&cell);
    return all_neighbors;
}

/// A sudoku board is represented by a vector of bytes.
#[derive(Debug)]
struct SudokuBoard(Vec<BTreeSet<usize>>);

impl SudokuBoard {
    /// Create a new sudoku board from a string.
    /// A non-zero digit stands for itself,
    /// a dot stands for a blank cell,
    /// anything else is an error.
    fn from_str(digits: &str) -> Self {
        if digits.len() != NSQ {
            error(format!("invalid puzzle length; expected {}, got {}",
                          NSQ, digits.len()));
        }
        let mut v = Vec::with_capacity(NSQ);
        for d in digits.chars() {
            match d {
                '.' => {
                    let candidates: BTreeSet<usize> = (1 .. N+1).collect();
                    v.push(candidates);
                }
                '1' ... '9' => {
                    let mut singleton = BTreeSet::new();
                    singleton.insert(d.to_digit(10).unwrap() as usize);
                    v.push(singleton);
                }
                _ => { error(format!("invalid digit ({:?}) in string", d)); }
            }
        }
        SudokuBoard(v)
    }

    fn cell_solved(&self, cell: usize) -> bool {
        self.0[cell].len() == 1
    }

    fn cell_solvable(&self, cell: usize) -> bool {
        self.0[cell].len() != 0
    }

    fn solved(&self) -> bool {
        (0 .. NSQ).all(|cell| self.cell_solved(cell))
    }

    fn solvable(&self) -> bool {
        (0 .. NSQ).all(|cell| self.cell_solvable(cell))
    }

    fn non_candidates(&self, cell: usize) -> BTreeSet<usize> {
        let mut set: BTreeSet<usize> = BTreeSet::new();
        for n in neighbors(cell) {
            if self.cell_solved(n) {
                for x in self.0[n].iter() {
                    set.insert(*x);
                }
            }
        }
        set
    }

    fn propagate(&self) -> Self {
        let mut output = SudokuBoard(self.0.clone());
        loop {
            let mut candidates_changed = false;
            for i in 0 .. NSQ {
                for nc in output.non_candidates(i) {
                    let q = output.0[i].remove(&nc);
                    candidates_changed = q || candidates_changed;
                }
            }
            if !candidates_changed {
                break;
            }
        }
        return output;
    }

    fn solve(&self, cell: usize) -> Option<Self> {
        if cell >= NSQ {
            return Some(SudokuBoard(self.0.clone()));
        }

        if self.cell_solved(cell) {
            return self.solve(cell + 1);
        }

        let mut newboard = self.propagate();

        if newboard.solved() {
            return Some(newboard);
        }

        if !newboard.solvable() {
            return None;
        }

        let cell_candidates = newboard.0[cell].clone();
        for c in cell_candidates.iter() {
            newboard.0[cell].clear();
            newboard.0[cell].insert(*c);
            match newboard.solve(cell + 1) {
                Some(solved_board) => { return Some(solved_board); }
                None => { }
            }
        }

        return None;
    }

    fn debug(&self) {
        for i in 0 .. NSQ {
            println!("[{:?}]", self.0[i]);
        }
    }
}

fn main() {
    let stdin = io::stdin();
    let mut buf = String::with_capacity(NSQ);

    loop {
        buf.clear();
        match stdin.read_line(&mut buf) {
            Err(e) => { error(format!("I/O error, {:?}", e)); }
            Ok(0) => { return; }
            Ok(_) => { /* pass through */ }
        }
        let sb = SudokuBoard::from_str(&buf.trim());
        match sb.solve(0) {
            Some(_) => { println!("OK"); }
            None => { println!("No solution"); }
        }
    }
}

/*
#[test]
fn test_row_col() {
    assert_eq!(row(11), 1);
    assert_eq!(col(11), 2);
}

#[test]
fn test_group() {
    assert_eq!(group(0), 0);
    assert_eq!(group(1), 0);
    assert_eq!(group(2), 0);
    assert_eq!(group(9), 0);
    assert_eq!(group(10), 0);
    assert_eq!(group(11), 0);
    assert_eq!(group(18), 0);
    assert_eq!(group(19), 0);
    assert_eq!(group(20), 0);
    assert_eq!(group(60), 60);
    assert_eq!(group(61), 60);
    assert_eq!(group(62), 60);
    assert_eq!(group(69), 60);
    assert_eq!(group(70), 60);
    assert_eq!(group(71), 60);
    assert_eq!(group(78), 60);
    assert_eq!(group(79), 60);
    assert_eq!(group(80), 60);
}

#[test]
fn test_is_solved() {
    let sb = SudokuBoard(vec![0, 1]);
    assert!(!sb.is_solved(0));
    assert!(sb.is_solved(1));
}

#[test]
fn test_neighbors() {
    assert!(!neighbors(0).contains(&0));
    // Neighbors of 0 on the same row
    assert!(neighbors(0).contains(&1));
    assert!(neighbors(0).contains(&2));
    assert!(neighbors(0).contains(&3));
    assert!(neighbors(0).contains(&4));
    assert!(neighbors(0).contains(&5));
    assert!(neighbors(0).contains(&6));
    assert!(neighbors(0).contains(&7));
    assert!(neighbors(0).contains(&8));
    // Neighbors of 0 on the same col
    assert!(neighbors(0).contains(&9));
    assert!(neighbors(0).contains(&18));
    assert!(neighbors(0).contains(&27));
    assert!(neighbors(0).contains(&36));
    assert!(neighbors(0).contains(&45));
    assert!(neighbors(0).contains(&54));
    assert!(neighbors(0).contains(&63));
    assert!(neighbors(0).contains(&72));
    // Neighbors of 0 in the same group
    assert!(neighbors(0).contains(&1));
    assert!(neighbors(0).contains(&2));
    assert!(neighbors(0).contains(&9));
    assert!(neighbors(0).contains(&10));
    assert!(neighbors(0).contains(&11));
    assert!(neighbors(0).contains(&18));
    assert!(neighbors(0).contains(&19));
    assert!(neighbors(0).contains(&20));
}

#[test]
fn test_candidates() {
    let sb = SudokuBoard::from_str(".2......34..........6...................................................5........");
    assert!(!sb.candidates(0).contains(&2));
    assert!(!sb.candidates(0).contains(&3));
    assert!(!sb.candidates(0).contains(&4));
    assert!(!sb.candidates(0).contains(&5));
    assert!(!sb.candidates(0).contains(&6));
    assert!(sb.candidates(0).contains(&1));
    assert!(sb.candidates(0).contains(&7));
    assert!(sb.candidates(0).contains(&8));
    assert!(sb.candidates(0).contains(&9));
}
*/
<|endoftext|>


<commit_before>
use std::ops::{Index, IndexMut};
use value::Value;
use error::Error;

// top level key that contains everything is __top_level__
#[derive(Clone, Debug, PartialEq)]
/// Structure that represents a key-value pair.
pub struct Pair {
    pub key: Value,
    pub value: Vec<Pair>
}

impl Pair {
    /// Creates a new Pair.
    ///
    /// # Examples
    ///
    /// Any type where [`Value`] implements `From` can be supplied:
    ///
    /// ```
    /// # use nccl::Pair;
    /// let p1 = Pair::new("Hello!");
    /// let p2 = Pair::new(true);
    /// // etc
    /// ```
    ///
    /// [`Value`]: ../value/enum.Value.html
    pub fn new<T>(key: T) -> Pair where Value: From<T> {
        Pair {
            key: Value::from(key),
            value: vec![]
        }
    }

    /// Adds a [`Value`] to a Pair. Overwrites values if they exist.
    ///
    /// # Examples
    ///
    /// Any type where [`Value`] implements `From` can be supplied:
    ///
    /// ```
    /// # use nccl::Pair;
    /// let mut p = Pair::new("top");
    /// p.add("hello");
    /// p.add(6.28);
    /// ```
    ///
    /// `add` overwrites values if they exist:
    ///
    /// ```
    /// # use nccl::Pair;
    /// let mut p = Pair::new("top");
    /// p.add("hello");
    /// p["hello"].add("everyone");
    /// p.add("hello");
    ///
    /// assert_eq!(p["hello"], Pair {
    ///     key: "hello".into(),
    ///     value: vec![]
    /// });
    /// ```
    ///
    /// [`Value`]: ../value/enum.Value.html
    pub fn add<T>(&mut self, val: T) where Value: From<T> {
        self.add_pair(Pair::new(val));
    }

    /// Adds a Pair to a Pair. Overwrites values if they exist.
    ///
    /// # Examples
    ///
    /// ```
    /// # use nccl::Pair;
    /// // create a new Pair
    /// let mut p1 = Pair::new("hi");
    ///
    /// // add some stuff to the pair
    /// p1.add("people");
    /// p1.add("friends");
    ///
    /// // we want to say hello some more
    /// let mut p2 = Pair::new("friends");
    ///
    /// // add some friends
    /// p2.add("John");
    /// p2.add("Alex");
    ///
    /// // say hello to our friends
    /// p1.add_pair(p2);
    /// ```
    ///
    /// `add_pair` overwrites values if they exist:
    ///
    /// ```
    /// # use nccl::Pair;
    /// // create a new pair
    /// let mut p1 = Pair::new("happy birthday");
    ///
    /// // we think Ron's birthday is the 3rd...
    /// p1.add("Ron");
    /// p1["Ron"].add("March 3rd");
    ///
    /// // whoops, we were wrong
    /// let mut p2 = Pair::new("Ron");
    /// p2.add("March 2nd");
    ///
    /// // there you go Ron, happy belated birthday
    /// p1.add_pair(p2);
    /// ```
    pub fn add_pair(&mut self, pair: Pair) {
        if !self.value.contains(&pair) {
            self.value.push(pair);
        } else {
            self[pair.key].value = pair.value;
        }
    }

    /// Gets an immutable reference to a Pair in a Pair.
    pub fn get(&self, value: Value) -> Result<&Pair, Error> {
        let mut p = None;
        for (k, v) in self.value.iter().enumerate() {
            if v.key == value {
                p = Some(k);
            }
        }
        if p.is_some() {
            Ok(&self.value[p.unwrap()])
        } else {
            Err(Error::KeyNotFound)
        }
    }

    /// Gets a mutable reference to a Pair in a Pair.
    ///
    /// # Examples
    ///
    /// ```
    /// # use nccl::Pair;
    /// let mut p = Pair::new("heyo");
    /// p.add("waddup");
    /// p["waddup"].add("my pal");
    ///
    /// // indexing calls get/get_mut under the hood
    /// p.get_mut("waddup".into()).unwrap().add("friend");
    /// // equivalent to
    /// p["waddup"].add("friend");
    /// ```
    pub fn get_mut(&mut self, value: Value) -> Result<&mut Pair, Error> {
        let mut p = None;
        for (k, v) in self.value.iter().enumerate() {
            if v.key == value {
                p = Some(k);
            }
        }
        if p.is_some() {
            Ok(&mut self.value[p.unwrap()])
        } else {
            Err(Error::KeyNotFound)
        }
    }
}

impl<T> Index<T> for Pair where Value: From<T> {
    type Output = Pair;
    fn index(&self, value: T) -> &Pair {
        self.get(value.into()).expect("Did not find value in pair")
    }
}

impl<T> IndexMut<T> for Pair where Value: From<T> {
    fn index_mut(&mut self, value: T) -> &mut Pair {
        self.get_mut(value.into()).expect("Did not find value in pair")
    }
}

impl Index<Pair> for Pair {
    type Output = Pair;
    fn index(&self, value: Pair) -> &Pair {
        self.get(value.key).expect("Did not find value in pair")
    }
}

impl IndexMut<Pair> for Pair {
    fn index_mut(&mut self, value: Pair) -> &mut Pair {
        self.get_mut(value.key).expect("Did not find value in pair")
    }
}

<commit_msg>rename functions<commit_after>
use std::ops::{Index, IndexMut};
use value::Value;
use error::Error;

// top level key that contains everything is __top_level__
#[derive(Clone, Debug, PartialEq)]
/// Structure that represents a key-value pair.
pub struct Pair {
    pub key: Value,
    pub value: Vec<Pair>
}

impl Pair {
    /// Creates a new Pair.
    ///
    /// # Examples
    ///
    /// Any type where [`Value`] implements `From` can be supplied:
    ///
    /// ```
    /// # use nccl::Pair;
    /// let p1 = Pair::new("Hello!");
    /// let p2 = Pair::new(true);
    /// // etc
    /// ```
    ///
    /// [`Value`]: ../value/enum.Value.html
    pub fn new<T>(key: T) -> Pair where Value: From<T> {
        Pair {
            key: Value::from(key),
            value: vec![]
        }
    }

    /// Adds a [`Value`] to a Pair. Overwrites values if they exist.
    ///
    /// # Examples
    ///
    /// Any type where [`Value`] implements `From` can be supplied:
    ///
    /// ```
    /// # use nccl::Pair;
    /// let mut p = Pair::new("top");
    /// p.add("hello");
    /// p.add(6.28);
    /// ```
    ///
    /// `add` overwrites values if they exist:
    ///
    /// ```
    /// # use nccl::Pair;
    /// let mut p = Pair::new("top");
    /// p.add("hello");
    /// p["hello"].add("everyone");
    /// p.add("hello");
    ///
    /// assert_eq!(p["hello"], Pair {
    ///     key: "hello".into(),
    ///     value: vec![]
    /// });
    /// ```
    ///
    /// [`Value`]: ../value/enum.Value.html
    pub fn add<T>(&mut self, val: T) where Value: From<T> {
        self.add_pair(Pair::new(val));
    }

    /// Adds a Pair to a Pair. Overwrites values if they exist.
    ///
    /// # Examples
    ///
    /// ```
    /// # use nccl::Pair;
    /// // create a new Pair
    /// let mut p1 = Pair::new("hi");
    ///
    /// // add some stuff to the pair
    /// p1.add("people");
    /// p1.add("friends");
    ///
    /// // we want to say hello some more
    /// let mut p2 = Pair::new("friends");
    ///
    /// // add some friends
    /// p2.add("John");
    /// p2.add("Alex");
    ///
    /// // say hello to our friends
    /// p1.add_pair(p2);
    /// ```
    ///
    /// `add_pair` overwrites values if they exist:
    ///
    /// ```
    /// # use nccl::Pair;
    /// // create a new pair
    /// let mut p1 = Pair::new("happy birthday");
    ///
    /// // we think Ron's birthday is the 3rd...
    /// p1.add("Ron");
    /// p1["Ron"].add("March 3rd");
    ///
    /// // whoops, we were wrong
    /// let mut p2 = Pair::new("Ron");
    /// p2.add("March 2nd");
    ///
    /// // there you go Ron, happy belated birthday
    /// p1.add_pair(p2);
    /// ```
    pub fn add_pair(&mut self, pair: Pair) {
        if !self.value.contains(&pair) {
            self.value.push(pair);
        } else {
            self[pair.key].value = pair.value;
        }
    }

    /// Gets an immutable reference to a Pair in a Pair.
    pub fn get_pair(&self, value: Value) -> Result<&Pair, Error> {
        let mut p = None;
        for (k, v) in self.value.iter().enumerate() {
            if v.key == value {
                p = Some(k);
            }
        }
        if p.is_some() {
            Ok(&self.value[p.unwrap()])
        } else {
            Err(Error::KeyNotFound)
        }
    }

    /// Gets a mutable reference to a Pair in a Pair.
    ///
    /// # Examples
    ///
    /// ```
    /// # use nccl::Pair;
    /// let mut p = Pair::new("heyo");
    /// p.add("waddup");
    /// p["waddup"].add("my pal");
    ///
    /// // indexing calls get/get_mut under the hood
    /// p.get_pair_mut("waddup".into()).unwrap().add("friend");
    /// // equivalent to
    /// p["waddup"].add("friend");
    /// ```
    pub fn get_pair_mut(&mut self, value: Value) -> Result<&mut Pair, Error> {
        let mut p = None;
        for (k, v) in self.value.iter().enumerate() {
            if v.key == value {
                p = Some(k);
            }
        }
        if p.is_some() {
            Ok(&mut self.value[p.unwrap()])
        } else {
            Err(Error::KeyNotFound)
        }
    }

    /// Gets the value associated with a pair.
    ///
    /// # Examples
    ///
    /// ```
    /// # use nccl::Pair;
    /// let mut p = Pair::new("numbers");
    /// p.add("one");
    /// p.add("two");
    /// p["one"].add(true);
    /// p["two"].add(false);
    /// assert_eq!(*p["one"].get(), true.into());
    /// assert_eq!(*p["two"].get(), false.into());
    /// ```
    pub fn get(&self) -> &Value {
        if self.value.len() == 0 {
            panic!("No value associated with key");
        }
        &self.value[0].key
    }
}

impl<T> Index<T> for Pair where Value: From<T> {
    type Output = Pair;
    fn index(&self, value: T) -> &Pair {
        self.get_pair(value.into()).expect("Did not find value in pair")
    }
}

impl<T> IndexMut<T> for Pair where Value: From<T> {
    fn index_mut(&mut self, value: T) -> &mut Pair {
        self.get_pair_mut(value.into()).expect("Did not find value in pair")
    }
}

<|endoftext|>


<commit_before>extern crate websocket;

use std::thread;
use websocket::{Server, Message, Sender, Receiver};
use websocket::header::WebSocketProtocol;

extern crate iron;

use iron::prelude::*;
use iron::status;
use iron::mime::Mime;
use std::fs;
use std::fs::File;
use std::path::Path;
use std::os;
use std::env;
use std::io::Read;
use std::string::*;

extern crate serde_json;
use serde_json::Value;

fn main() {

    let args = env::args();
    let mut iter = args.skip(1); // skip the program name

    let mut s = String::new();

    match iter.next() {
      Some(file_name) => {
        println!("{}", file_name);
        let path = &Path::new(&file_name);
        let f = File::open(path);
        match f {
          Ok(mut of) => {
            match of.read_to_string(&mut s) {
              Err(e) => {
                println!("err: {:?}", e);
                return ();
                },
              Ok(len) => {
                println!("read {} bytes", len)
                },
            }
            },
          Err(e) => {
            println!("err: {:?}", e);
            return ();
            },
          }
        println!("serving file: {}", file_name);
        println!("from localhost:3000");

        let data: Value = serde_json::from_str(&s[..]).unwrap();

        println!("serdeval: {:?}", data);

        }
      None => {
        println!("no args!");
        }
    }

    thread::spawn(move || {
      winsockets_main();
      });

    Iron::new(move |req: &mut Request| {
        let content_type = "text/html".parse::<Mime>().unwrap();
        Ok(Response::with((content_type, status::Ok, &*s)))
    }).http("localhost:3000").unwrap();
}

fn winsockets_main() {
	let server = Server::bind("127.0.0.1:1234").unwrap();

	for connection in server {
		// Spawn a new thread for each connection.
		thread::spawn(move || {
			let request = connection.unwrap().read_request().unwrap(); // Get the request
			let headers = request.headers.clone(); // Keep the headers so we can check them

			request.validate().unwrap(); // Validate the request

			let mut response = request.accept(); // Form a response

			if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
				if protocols.contains(&("rust-websocket".to_string())) {
					// We have a protocol we want to use
					response.headers.set(WebSocketProtocol(vec!["rust-websocket".to_string()]));
				}
			}

			let mut client = response.send().unwrap(); // Send the response

			let ip = client.get_mut_sender()
				.get_mut()
				.peer_addr()
				.unwrap();

			println!("Connection from {}", ip);

			let message = Message::Text("Hello".to_string());
			client.send_message(message).unwrap();

			let (mut sender, mut receiver) = client.split();

			for message in receiver.incoming_messages() {
				let message = message.unwrap();
        println!("message: {:?}", message);

        let replyy = Message::Text("replyyyblah".to_string());

				match message {
					Message::Close(_) => {
						let message = Message::Close(None);
						sender.send_message(message).unwrap();
						println!("Client {} disconnected", ip);
						return;
					}
					Message::Ping(data) => {
            println!("Message::Ping(data)");
						let message = Message::Pong(data);
						sender.send_message(message).unwrap();
					}
					// _ => sender.send_message(message).unwrap(),
					_ => {
            println!("sending replyy");
            sender.send_message(replyy).unwrap()
            }
				}
			}
		});
	}
}

<commit_msg>serving up the passed-in file via websockets.<commit_after>extern crate websocket;

use std::thread;
use websocket::{Server, Message, Sender, Receiver};
use websocket::header::WebSocketProtocol;

extern crate iron;

use iron::prelude::*;
use iron::status;
use iron::mime::Mime;
use std::fs;
use std::fs::File;
use std::path::Path;
use std::os;
use std::env;
use std::io::Read;
use std::string::*;

extern crate serde_json;
use serde_json::Value;

fn main() {

    let args = env::args();
    let mut iter = args.skip(1); // skip the program name

    let mut s = String::new();

    match iter.next() {
      Some(file_name) => {
        println!("{}", file_name);
        let path = &Path::new(&file_name);
        let f = File::open(path);
        match f {
          Ok(mut of) => {
            match of.read_to_string(&mut s) {
              Err(e) => {
                println!("err: {:?}", e);
                return ();
                },
              Ok(len) => {
                println!("read {} bytes", len)
                },
            }
            },
          Err(e) => {
            println!("err: {:?}", e);
            return ();
            },
          }
        println!("serving file: {}", file_name);
        println!("from localhost:3030");

        let data: Value = serde_json::from_str(&s[..]).unwrap();

        println!("serdeval: {:?}", data);
        }
      None => {
        println!("no args!");
        }
    }

    let q = String::new() + &s[..];

    thread::spawn(move || {
      winsockets_main(q);
      });

    Iron::new(move |req: &mut Request| {
        let content_type = "text/html".parse::<Mime>().unwrap();
        Ok(Response::with((content_type, status::Ok, &*s)))
    }).http("localhost:3030").unwrap();
}

fn winsockets_main(aSConfig: String) {
	let server = Server::bind("127.0.0.1:1234").unwrap();

	for connection in server {
		// Spawn a new thread for each connection.
    let blah = String::new() + &aSConfig[..];

    thread::spawn(move || {
			let request = connection.unwrap().read_request().unwrap(); // Get the request
			let headers = request.headers.clone(); // Keep the headers so we can check them

			request.validate().unwrap(); // Validate the request

			let mut response = request.accept(); // Form a response

			if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
				if protocols.contains(&("rust-websocket".to_string())) {
					// We have a protocol we want to use
					response.headers.set(WebSocketProtocol(vec!["rust-websocket".to_string()]));
				}
			}

			let mut client = response.send().unwrap(); // Send the response

			let ip = client.get_mut_sender()
				.get_mut()
				.peer_addr()
				.unwrap();

			println!("Connection from {}", ip);

      let message = Message::Text(blah);
			client.send_message(message.clone()).unwrap();

			let (mut sender, mut receiver) = client.split();

			for message in receiver.incoming_messages() {
				let message = message.unwrap();
        println!("message: {:?}", message);

        let replyy = Message::Text("replyyyblah".to_string());

				match message {
					Message::Close(_) => {
						let message = Message::Close(None);
						sender.send_message(message).unwrap();
						println!("Client {} disconnected", ip);
						return;
					}
					Message::Ping(data) => {
            println!("Message::Ping(data)");
						let message = Message::Pong(data);
						sender.send_message(message).unwrap();
					}
					// _ => sender.send_message(message).unwrap(),
					_ => {
            println!("sending replyy");
            sender.send_message(replyy).unwrap()
            }
				}
			}
		});
	}
}

<|endoftext|>


<commit_before>mod rsh;

use std::env;

fn main() {
    let mut argv = env::args();

    let path = argv.
        next().
        unwrap_or(".".to_string());

    let s = rsh::State::new(path);
    rsh::run(s)
}
<commit_msg>make state mutable<commit_after>mod rsh;

use std::env;

fn main() {
    let mut argv = env::args();

    let path = argv.
        next().
        unwrap_or(".".to_string());

    let mut s = rsh::State::new(path);
    rsh::run(s)
}
<|endoftext|>