<commit_before>//! ARM ABI implementation.

use super::registers::{D, GPR, Q, S};
use crate::abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion};
use crate::ir::{self, AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, Type};
use crate::isa::RegClass;
use crate::regalloc::RegisterSet;
use core::i32;
use target_lexicon::Triple;

struct Args {
    pointer_bits: u8,
    pointer_bytes: u8,
    pointer_type: Type,
    regs: u32,
    reg_limit: u32,
    offset: u32,
}

impl Args {
    fn new(bits: u8) -> Self {
        Self {
            pointer_bits: bits,
            pointer_bytes: bits / 8,
            pointer_type: Type::int(u16::from(bits)).unwrap(),
            regs: 0,
            reg_limit: 8,
            offset: 0,
        }
    }
}

impl ArgAssigner for Args {
    fn assign(&mut self, arg: &AbiParam) -> ArgAction {
        fn align(value: u32, to: u32) -> u32 {
            (value + to - 1) & !(to - 1)
        }

        let ty = arg.value_type;

        // Check for a legal type.
        // SIMD instructions are currently no implemented, so break down vectors
        if ty.is_vector() {
            return ValueConversion::VectorSplit.into();
        }

        // Large integers and booleans are broken down to fit in a register.
        if !ty.is_float() && ty.bits() > u16::from(self.pointer_bits) {
            // Align registers and stack to a multiple of two pointers.
            self.regs = align(self.regs, 2);
            self.offset = align(self.offset, 2 * u32::from(self.pointer_bytes));
            return ValueConversion::IntSplit.into();
        }

        // Small integers are extended to the size of a pointer register.
        if ty.is_int() && ty.bits() < u16::from(self.pointer_bits) {
            match arg.extension {
                ArgumentExtension::None => {}
                ArgumentExtension::Uext => return ValueConversion::Uext(self.pointer_type).into(),
                ArgumentExtension::Sext => return ValueConversion::Sext(self.pointer_type).into(),
            }
        }

        if self.regs < self.reg_limit {
            // Assign to a register.
            let reg = GPR.unit(10 + self.regs as usize);
            self.regs += 1;
            ArgumentLoc::Reg(reg).into()
        } else {
            // Assign a stack location.
            let loc = ArgumentLoc::Stack(self.offset as i32);
            self.offset += u32::from(self.pointer_bytes);
            debug_assert!(self.offset <= i32::MAX as u32);
            loc.into()
        }
    }
}

/// Legalize `sig`.
pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, current: bool) {
    let bits = triple.pointer_width().unwrap().bits();

    let mut args = Args::new(bits);
    legalize_args(&mut sig.params, &mut args);

    let mut rets = Args::new(bits);
    legalize_args(&mut sig.returns, &mut rets);

    if current {
        let ptr = Type::int(u16::from(bits)).unwrap();

        // Add the link register as an argument and return value.
        //
        // The `jalr` instruction implementing a return can technically accept the return address
        // in any register, but a micro-architecture with a return address predictor will only
        // recognize it as a return if the address is in `x1`.
        let link = AbiParam::special_reg(ptr, ArgumentPurpose::Link, GPR.unit(1));
        sig.params.push(link);
        sig.returns.push(link);
    }
}

/// Get register class for a type appearing in a legalized signature.
pub fn regclass_for_abi_type(ty: ir::Type) -> RegClass {
    if ty.is_int() {
        GPR
    } else {
        match ty.bits() {
            32 => S,
            64 => D,
            128 => Q,
            _ => panic!("Unexpected {} ABI type for arm32", ty),
        }
    }
}

/// Get the set of allocatable registers for `func`.
pub fn allocatable_registers(_func: &ir::Function) -> RegisterSet {
    unimplemented!()
}
<commit_msg>Adding comment about copying RiscV abi file into ARM32.<commit_after>//! ARM ABI implementation.
//! This is from the RISC-V target and will need to be updated for ARM32.

use super::registers::{D, GPR, Q, S};
use crate::abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion};
use crate::ir::{self, AbiParam, ArgumentExtension, ArgumentLoc, Type};
use crate::isa::RegClass;
use crate::regalloc::RegisterSet;
use core::i32;
use target_lexicon::Triple;

struct Args {
    pointer_bits: u8,
    pointer_bytes: u8,
    pointer_type: Type,
    regs: u32,
    reg_limit: u32,
    offset: u32,
}

impl Args {
    fn new(bits: u8) -> Self {
        Self {
            pointer_bits: bits,
            pointer_bytes: bits / 8,
            pointer_type: Type::int(u16::from(bits)).unwrap(),
            regs: 0,
            reg_limit: 8,
            offset: 0,
        }
    }
}

impl ArgAssigner for Args {
    fn assign(&mut self, arg: &AbiParam) -> ArgAction {
        fn align(value: u32, to: u32) -> u32 {
            (value + to - 1) & !(to - 1)
        }

        let ty = arg.value_type;

        // Check for a legal type.
        // SIMD instructions are currently no implemented, so break down vectors
        if ty.is_vector() {
            return ValueConversion::VectorSplit.into();
        }

        // Large integers and booleans are broken down to fit in a register.
        if !ty.is_float() && ty.bits() > u16::from(self.pointer_bits) {
            // Align registers and stack to a multiple of two pointers.
            self.regs = align(self.regs, 2);
            self.offset = align(self.offset, 2 * u32::from(self.pointer_bytes));
            return ValueConversion::IntSplit.into();
        }

        // Small integers are extended to the size of a pointer register.
        if ty.is_int() && ty.bits() < u16::from(self.pointer_bits) {
            match arg.extension {
                ArgumentExtension::None => {}
                ArgumentExtension::Uext => return ValueConversion::Uext(self.pointer_type).into(),
                ArgumentExtension::Sext => return ValueConversion::Sext(self.pointer_type).into(),
            }
        }

        if self.regs < self.reg_limit {
            // Assign to a register.
            let reg = GPR.unit(10 + self.regs as usize);
            self.regs += 1;
            ArgumentLoc::Reg(reg).into()
        } else {
            // Assign a stack location.
            let loc = ArgumentLoc::Stack(self.offset as i32);
            self.offset += u32::from(self.pointer_bytes);
            debug_assert!(self.offset <= i32::MAX as u32);
            loc.into()
        }
    }
}

/// Legalize `sig`.
pub fn legalize_signature(sig: &mut ir::Signature, triple: &Triple, _current: bool) {
    let bits = triple.pointer_width().unwrap().bits();

    let mut args = Args::new(bits);
    legalize_args(&mut sig.params, &mut args);
}

/// Get register class for a type appearing in a legalized signature.
pub fn regclass_for_abi_type(ty: ir::Type) -> RegClass {
    if ty.is_int() {
        GPR
    } else {
        match ty.bits() {
            32 => S,
            64 => D,
            128 => Q,
            _ => panic!("Unexpected {} ABI type for arm32", ty),
        }
    }
}

/// Get the set of allocatable registers for `func`.
pub fn allocatable_registers(_func: &ir::Function) -> RegisterSet {
    unimplemented!()
}
<|endoftext|>


<commit_before>//! Handles build script specific information

use std::{
    path::PathBuf,
    process::{Command, Stdio},
    sync::Arc,
};

use anyhow::Result;
use cargo_metadata::camino::Utf8Path;
use cargo_metadata::{BuildScript, Message};
use paths::{AbsPath, AbsPathBuf};
use rustc_hash::FxHashMap;
use serde::Deserialize;
use stdx::format_to;

use crate::{cfg_flag::CfgFlag, CargoConfig};

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub(crate) struct PackageBuildData {
    /// List of config flags defined by this package's build script
    pub(crate) cfgs: Vec<CfgFlag>,
    /// List of cargo-related environment variables with their value
    ///
    /// If the package has a build script which defines environment variables,
    /// they can also be found here.
    pub(crate) envs: Vec<(String, String)>,
    /// Directory where a build script might place its output
    pub(crate) out_dir: Option<AbsPathBuf>,
    /// Path to the proc-macro library file if this package exposes proc-macros
    pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>,
}

#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub(crate) struct WorkspaceBuildData {
    per_package: FxHashMap<String, PackageBuildData>,
    error: Option<String>,
}

#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub struct BuildDataResult {
    per_workspace: FxHashMap<AbsPathBuf, WorkspaceBuildData>,
}

#[derive(Clone, Debug)]
pub(crate) struct BuildDataConfig {
    cargo_toml: AbsPathBuf,
    cargo_features: CargoConfig,
    packages: Arc<Vec<cargo_metadata::Package>>,
}

impl PartialEq for BuildDataConfig {
    fn eq(&self, other: &Self) -> bool {
        Arc::ptr_eq(&self.packages, &other.packages)
    }
}

impl Eq for BuildDataConfig {}

#[derive(Debug)]
pub struct BuildDataCollector {
    wrap_rustc: bool,
    configs: FxHashMap<AbsPathBuf, BuildDataConfig>,
}

impl BuildDataCollector {
    pub fn new(wrap_rustc: bool) -> Self {
        Self { wrap_rustc, configs: FxHashMap::default() }
    }

    pub(crate) fn add_config(&mut self, workspace_root: &AbsPath, config: BuildDataConfig) {
        self.configs.insert(workspace_root.to_path_buf(), config);
    }

    pub fn collect(&mut self, progress: &dyn Fn(String)) -> Result<BuildDataResult> {
        let mut res = BuildDataResult::default();
        for (path, config) in self.configs.iter() {
            let workspace_build_data = WorkspaceBuildData::collect(
                &config.cargo_toml,
                &config.cargo_features,
                &config.packages,
                self.wrap_rustc,
                progress,
            )?;
            res.per_workspace.insert(path.clone(), workspace_build_data);
        }
        Ok(res)
    }
}

impl WorkspaceBuildData {
    pub(crate) fn get(&self, package_id: &str) -> Option<&PackageBuildData> {
        self.per_package.get(package_id)
    }
}

impl BuildDataResult {
    pub(crate) fn get(&self, workspace_root: &AbsPath) -> Option<&WorkspaceBuildData> {
        self.per_workspace.get(workspace_root)
    }
    pub fn error(&self) -> Option<String> {
        let mut buf = String::new();
        for (_workspace_root, build_data) in &self.per_workspace {
            if let Some(err) = &build_data.error {
                format_to!(buf, "cargo check failed:\n{}", err);
            }
        }
        if buf.is_empty() {
            return None;
        }

        Some(buf)
    }
}

impl BuildDataConfig {
    pub(crate) fn new(
        cargo_toml: AbsPathBuf,
        cargo_features: CargoConfig,
        packages: Arc<Vec<cargo_metadata::Package>>,
    ) -> Self {
        Self { cargo_toml, cargo_features, packages }
    }
}

impl WorkspaceBuildData {
    fn collect(
        cargo_toml: &AbsPath,
        cargo_features: &CargoConfig,
        packages: &Vec<cargo_metadata::Package>,
        wrap_rustc: bool,
        progress: &dyn Fn(String),
    ) -> Result<WorkspaceBuildData> {
        let mut cmd = Command::new(toolchain::cargo());

        if wrap_rustc {
            // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
            // that to compile only proc macros and build scripts during the initial
            // `cargo check`.
            let myself = std::env::current_exe()?;
            cmd.env("RUSTC_WRAPPER", myself);
            cmd.env("RA_RUSTC_WRAPPER", "1");
        }

        cmd.current_dir(cargo_toml.parent().unwrap());
        cmd.args(&["check", "--quiet", "--workspace", "--message-format=json", "--manifest-path"])
            .arg(cargo_toml.as_ref());

        // --all-targets includes tests, benches and examples in addition to the
        // default lib and bins. This is an independent concept from the --targets
        // flag below.
        cmd.arg("--all-targets");

        if let Some(target) = &cargo_features.target {
            cmd.args(&["--target", target]);
        }

        if cargo_features.all_features {
            cmd.arg("--all-features");
        } else {
            if cargo_features.no_default_features {
                // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures`
                // https://github.com/oli-obk/cargo_metadata/issues/79
                cmd.arg("--no-default-features");
            }
            if !cargo_features.features.is_empty() {
                cmd.arg("--features");
                cmd.arg(cargo_features.features.join(" "));
            }
        }

        cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());

        let mut res = WorkspaceBuildData::default();

        let mut callback_err = None;
        let output = stdx::process::streaming_output(
            cmd,
            &mut |line| {
                if callback_err.is_some() {
                    return;
                }

                // Copy-pasted from existing cargo_metadata. It seems like we
                // should be using sered_stacker here?
                let mut deserializer = serde_json::Deserializer::from_str(line);
                deserializer.disable_recursion_limit();
                let message = Message::deserialize(&mut deserializer)
                    .unwrap_or_else(|_| Message::TextLine(line.to_string()));

                match message {
                    Message::BuildScriptExecuted(BuildScript {
                        package_id,
                        out_dir,
                        cfgs,
                        env,
                        ..
                    }) => {
                        let cfgs = {
                            let mut acc = Vec::new();
                            for cfg in cfgs {
                                match cfg.parse::<CfgFlag>() {
                                    Ok(it) => acc.push(it),
                                    Err(err) => {
                                        callback_err = Some(anyhow::format_err!(
                                            "invalid cfg from cargo-metadata: {}",
                                            err
                                        ));
                                        return;
                                    }
                                };
                            }
                            acc
                        };
                        let package_build_data =
                            res.per_package.entry(package_id.repr).or_default();
                        // cargo_metadata crate returns default (empty) path for
                        // older cargos, which is not absolute, so work around that.
                        if !out_dir.as_str().is_empty() {
                            let out_dir =
                                AbsPathBuf::assert(PathBuf::from(out_dir.into_os_string()));
                            package_build_data.out_dir = Some(out_dir);
                            package_build_data.cfgs = cfgs;
                        }

                        package_build_data.envs = env;
                    }
                    Message::CompilerArtifact(message) => {
                        progress(format!("metadata {}", message.target.name));

                        if message.target.kind.iter().any(|k| k == "proc-macro") {
                            let package_id = message.package_id;
                            // Skip rmeta file
                            if let Some(filename) =
                                message.filenames.iter().find(|name| is_dylib(name))
                            {
                                let filename = AbsPathBuf::assert(PathBuf::from(&filename));
                                let package_build_data =
                                    res.per_package.entry(package_id.repr).or_default();
                                package_build_data.proc_macro_dylib_path = Some(filename);
                            }
                        }
                    }
                    Message::CompilerMessage(message) => {
                        progress(message.target.name);
                    }
                    Message::BuildFinished(_) => {}
                    Message::TextLine(_) => {}
                    _ => {}
                }
            },
            &mut |_| (),
        )?;

        for package in packages {
            let package_build_data = res.per_package.entry(package.id.repr.clone()).or_default();
            inject_cargo_env(package, package_build_data);
            if let Some(out_dir) = &package_build_data.out_dir {
                // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
                if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) {
                    package_build_data.envs.push(("OUT_DIR".to_string(), out_dir));
                }
            }
        }

        if !output.status.success() {
            let mut stderr = String::from_utf8(output.stderr).unwrap_or_default();
            if stderr.is_empty() {
                stderr = "cargo check failed".to_string();
            }
            res.error = Some(stderr)
        }

        Ok(res)
    }
}

// FIXME: File a better way to know if it is a dylib
fn is_dylib(path: &Utf8Path) -> bool {
    match path.extension().map(|e| e.to_string().to_lowercase()) {
        None => false,
        Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"),
    }
}

/// Recreates the compile-time environment variables that Cargo sets.
///
/// Should be synced with <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>
fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut PackageBuildData) {
    let env = &mut build_data.envs;

    // FIXME: Missing variables:
    // CARGO_PKG_HOMEPAGE, CARGO_CRATE_NAME, CARGO_BIN_NAME, CARGO_BIN_EXE_<name>

    let mut manifest_dir = package.manifest_path.clone();
    manifest_dir.pop();
    env.push(("CARGO_MANIFEST_DIR".into(), manifest_dir.into_string()));

    // Not always right, but works for common cases.
    env.push(("CARGO".into(), "cargo".into()));

    env.push(("CARGO_PKG_VERSION".into(), package.version.to_string()));
    env.push(("CARGO_PKG_VERSION_MAJOR".into(), package.version.major.to_string()));
    env.push(("CARGO_PKG_VERSION_MINOR".into(), package.version.minor.to_string()));
    env.push(("CARGO_PKG_VERSION_PATCH".into(), package.version.patch.to_string()));
    env.push(("CARGO_PKG_VERSION_PRE".into(), package.version.pre.to_string()));

    let authors = package.authors.join(";");
    env.push(("CARGO_PKG_AUTHORS".into(), authors));

    env.push(("CARGO_PKG_NAME".into(), package.name.clone()));
    env.push(("CARGO_PKG_DESCRIPTION".into(), package.description.clone().unwrap_or_default()));
    //env.push(("CARGO_PKG_HOMEPAGE".into(), package.homepage.clone().unwrap_or_default()));
    env.push(("CARGO_PKG_REPOSITORY".into(), package.repository.clone().unwrap_or_default()));
    env.push(("CARGO_PKG_LICENSE".into(), package.license.clone().unwrap_or_default()));

    let license_file = package.license_file.as_ref().map(|buf| buf.to_string()).unwrap_or_default();
    env.push(("CARGO_PKG_LICENSE_FILE".into(), license_file));
}
<commit_msg>Set more `CARGO_` env vars<commit_after>//! Handles build script specific information

use std::{
    path::PathBuf,
    process::{Command, Stdio},
    sync::Arc,
};

use anyhow::Result;
use base_db::CrateName;
use cargo_metadata::camino::Utf8Path;
use cargo_metadata::{BuildScript, Message};
use paths::{AbsPath, AbsPathBuf};
use rustc_hash::FxHashMap;
use serde::Deserialize;
use stdx::format_to;

use crate::{cfg_flag::CfgFlag, CargoConfig};

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub(crate) struct PackageBuildData {
    /// List of config flags defined by this package's build script
    pub(crate) cfgs: Vec<CfgFlag>,
    /// List of cargo-related environment variables with their value
    ///
    /// If the package has a build script which defines environment variables,
    /// they can also be found here.
    pub(crate) envs: Vec<(String, String)>,
    /// Directory where a build script might place its output
    pub(crate) out_dir: Option<AbsPathBuf>,
    /// Path to the proc-macro library file if this package exposes proc-macros
    pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>,
}

#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub(crate) struct WorkspaceBuildData {
    per_package: FxHashMap<String, PackageBuildData>,
    error: Option<String>,
}

#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub struct BuildDataResult {
    per_workspace: FxHashMap<AbsPathBuf, WorkspaceBuildData>,
}

#[derive(Clone, Debug)]
pub(crate) struct BuildDataConfig {
    cargo_toml: AbsPathBuf,
    cargo_features: CargoConfig,
    packages: Arc<Vec<cargo_metadata::Package>>,
}

impl PartialEq for BuildDataConfig {
    fn eq(&self, other: &Self) -> bool {
        Arc::ptr_eq(&self.packages, &other.packages)
    }
}

impl Eq for BuildDataConfig {}

#[derive(Debug)]
pub struct BuildDataCollector {
    wrap_rustc: bool,
    configs: FxHashMap<AbsPathBuf, BuildDataConfig>,
}

impl BuildDataCollector {
    pub fn new(wrap_rustc: bool) -> Self {
        Self { wrap_rustc, configs: FxHashMap::default() }
    }

    pub(crate) fn add_config(&mut self, workspace_root: &AbsPath, config: BuildDataConfig) {
        self.configs.insert(workspace_root.to_path_buf(), config);
    }

    pub fn collect(&mut self, progress: &dyn Fn(String)) -> Result<BuildDataResult> {
        let mut res = BuildDataResult::default();
        for (path, config) in self.configs.iter() {
            let workspace_build_data = WorkspaceBuildData::collect(
                &config.cargo_toml,
                &config.cargo_features,
                &config.packages,
                self.wrap_rustc,
                progress,
            )?;
            res.per_workspace.insert(path.clone(), workspace_build_data);
        }
        Ok(res)
    }
}

impl WorkspaceBuildData {
    pub(crate) fn get(&self, package_id: &str) -> Option<&PackageBuildData> {
        self.per_package.get(package_id)
    }
}

impl BuildDataResult {
    pub(crate) fn get(&self, workspace_root: &AbsPath) -> Option<&WorkspaceBuildData> {
        self.per_workspace.get(workspace_root)
    }
    pub fn error(&self) -> Option<String> {
        let mut buf = String::new();
        for (_workspace_root, build_data) in &self.per_workspace {
            if let Some(err) = &build_data.error {
                format_to!(buf, "cargo check failed:\n{}", err);
            }
        }
        if buf.is_empty() {
            return None;
        }

        Some(buf)
    }
}

impl BuildDataConfig {
    pub(crate) fn new(
        cargo_toml: AbsPathBuf,
        cargo_features: CargoConfig,
        packages: Arc<Vec<cargo_metadata::Package>>,
    ) -> Self {
        Self { cargo_toml, cargo_features, packages }
    }
}

impl WorkspaceBuildData {
    fn collect(
        cargo_toml: &AbsPath,
        cargo_features: &CargoConfig,
        packages: &Vec<cargo_metadata::Package>,
        wrap_rustc: bool,
        progress: &dyn Fn(String),
    ) -> Result<WorkspaceBuildData> {
        let mut cmd = Command::new(toolchain::cargo());

        if wrap_rustc {
            // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
            // that to compile only proc macros and build scripts during the initial
            // `cargo check`.
            let myself = std::env::current_exe()?;
            cmd.env("RUSTC_WRAPPER", myself);
            cmd.env("RA_RUSTC_WRAPPER", "1");
        }

        cmd.current_dir(cargo_toml.parent().unwrap());
        cmd.args(&["check", "--quiet", "--workspace", "--message-format=json", "--manifest-path"])
            .arg(cargo_toml.as_ref());

        // --all-targets includes tests, benches and examples in addition to the
        // default lib and bins. This is an independent concept from the --targets
        // flag below.
        cmd.arg("--all-targets");

        if let Some(target) = &cargo_features.target {
            cmd.args(&["--target", target]);
        }

        if cargo_features.all_features {
            cmd.arg("--all-features");
        } else {
            if cargo_features.no_default_features {
                // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures`
                // https://github.com/oli-obk/cargo_metadata/issues/79
                cmd.arg("--no-default-features");
            }
            if !cargo_features.features.is_empty() {
                cmd.arg("--features");
                cmd.arg(cargo_features.features.join(" "));
            }
        }

        cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());

        let mut res = WorkspaceBuildData::default();

        let mut callback_err = None;
        let output = stdx::process::streaming_output(
            cmd,
            &mut |line| {
                if callback_err.is_some() {
                    return;
                }

                // Copy-pasted from existing cargo_metadata. It seems like we
                // should be using sered_stacker here?
                let mut deserializer = serde_json::Deserializer::from_str(line);
                deserializer.disable_recursion_limit();
                let message = Message::deserialize(&mut deserializer)
                    .unwrap_or_else(|_| Message::TextLine(line.to_string()));

                match message {
                    Message::BuildScriptExecuted(BuildScript {
                        package_id,
                        out_dir,
                        cfgs,
                        env,
                        ..
                    }) => {
                        let cfgs = {
                            let mut acc = Vec::new();
                            for cfg in cfgs {
                                match cfg.parse::<CfgFlag>() {
                                    Ok(it) => acc.push(it),
                                    Err(err) => {
                                        callback_err = Some(anyhow::format_err!(
                                            "invalid cfg from cargo-metadata: {}",
                                            err
                                        ));
                                        return;
                                    }
                                };
                            }
                            acc
                        };
                        let package_build_data =
                            res.per_package.entry(package_id.repr).or_default();
                        // cargo_metadata crate returns default (empty) path for
                        // older cargos, which is not absolute, so work around that.
                        if !out_dir.as_str().is_empty() {
                            let out_dir =
                                AbsPathBuf::assert(PathBuf::from(out_dir.into_os_string()));
                            package_build_data.out_dir = Some(out_dir);
                            package_build_data.cfgs = cfgs;
                        }

                        package_build_data.envs = env;
                    }
                    Message::CompilerArtifact(message) => {
                        progress(format!("metadata {}", message.target.name));

                        if message.target.kind.iter().any(|k| k == "proc-macro") {
                            let package_id = message.package_id;
                            // Skip rmeta file
                            if let Some(filename) =
                                message.filenames.iter().find(|name| is_dylib(name))
                            {
                                let filename = AbsPathBuf::assert(PathBuf::from(&filename));
                                let package_build_data =
                                    res.per_package.entry(package_id.repr).or_default();
                                package_build_data.proc_macro_dylib_path = Some(filename);
                            }
                        }
                    }
                    Message::CompilerMessage(message) => {
                        progress(message.target.name);
                    }
                    Message::BuildFinished(_) => {}
                    Message::TextLine(_) => {}
                    _ => {}
                }
            },
            &mut |_| (),
        )?;

        for package in packages {
            let package_build_data = res.per_package.entry(package.id.repr.clone()).or_default();
            inject_cargo_env(package, package_build_data);
            if let Some(out_dir) = &package_build_data.out_dir {
                // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
                if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) {
                    package_build_data.envs.push(("OUT_DIR".to_string(), out_dir));
                }
            }
        }

        if !output.status.success() {
            let mut stderr = String::from_utf8(output.stderr).unwrap_or_default();
            if stderr.is_empty() {
                stderr = "cargo check failed".to_string();
            }
            res.error = Some(stderr)
        }

        Ok(res)
    }
}

// FIXME: File a better way to know if it is a dylib
fn is_dylib(path: &Utf8Path) -> bool {
    match path.extension().map(|e| e.to_string().to_lowercase()) {
        None => false,
        Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"),
    }
}

/// Recreates the compile-time environment variables that Cargo sets.
///
/// Should be synced with <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>
fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut PackageBuildData) {
    let env = &mut build_data.envs;

    // FIXME: Missing variables:
    // CARGO_BIN_NAME, CARGO_BIN_EXE_<name>

    let mut manifest_dir = package.manifest_path.clone();
    manifest_dir.pop();
    env.push(("CARGO_MANIFEST_DIR".into(), manifest_dir.into_string()));

    // Not always right, but works for common cases.
    env.push(("CARGO".into(), "cargo".into()));

    env.push(("CARGO_PKG_VERSION".into(), package.version.to_string()));
    env.push(("CARGO_PKG_VERSION_MAJOR".into(), package.version.major.to_string()));
    env.push(("CARGO_PKG_VERSION_MINOR".into(), package.version.minor.to_string()));
    env.push(("CARGO_PKG_VERSION_PATCH".into(), package.version.patch.to_string()));
    env.push(("CARGO_PKG_VERSION_PRE".into(), package.version.pre.to_string()));

    let authors = package.authors.join(";");
    env.push(("CARGO_PKG_AUTHORS".into(), authors));

    env.push(("CARGO_PKG_NAME".into(), package.name.clone()));
    // FIXME: This isn't really correct (a package can have many crates with different names), but
    // it's better than leaving the variable unset.
    env.push(("CARGO_CRATE_NAME".into(), CrateName::normalize_dashes(&package.name).to_string()));
    env.push(("CARGO_PKG_DESCRIPTION".into(), package.description.clone().unwrap_or_default()));
    env.push(("CARGO_PKG_HOMEPAGE".into(), package.homepage.clone().unwrap_or_default()));
    env.push(("CARGO_PKG_REPOSITORY".into(), package.repository.clone().unwrap_or_default()));
    env.push(("CARGO_PKG_LICENSE".into(), package.license.clone().unwrap_or_default()));

    let license_file = package.license_file.as_ref().map(|buf| buf.to_string()).unwrap_or_default();
    env.push(("CARGO_PKG_LICENSE_FILE".into(), license_file));
}
<|endoftext|>


<commit_before>#![allow(unused_variables)]

enum Message {
   Quit,
   ChangeColor(i32, i32, i32),
   Move { x: i32, y: i32 },
   Write(String),
}

fn main() {

let x: Message = Message::Quit;
let y: Message = Message::ChangeColor(1,2,3);
let z: Message = Message::Move{x: 3,y: 4};
let p: Message = Message::Write("Rustacian".to_string());

enumtest(x);
enumtest(y);
enumtest(z);
enumtest(p);

}

fn enumtest(x: Message){
    match x {
        Message::Quit => println!("Quit"),
        Message::ChangeColor(r,g,b) => println!("ChangeColor r = {}, g = {}, b = {}", r,g,b),
        Message::Move{x,y} => println!("x = {}, y = {}",x,y),
        Message::Write(s) => println!("The passed string is {}",s),
    };

}
<commit_msg>Removed warning stopper<commit_after>enum Message {
   Quit,
   ChangeColor(i32, i32, i32),
   Move { x: i32, y: i32 },
   Write(String),
}

fn main() {

let x: Message = Message::Quit;
let y: Message = Message::ChangeColor(1,2,3);
let z: Message = Message::Move{x: 3,y: 4};
let p: Message = Message::Write("Rustacian".to_string());

enumtest(x);
enumtest(y);
enumtest(z);
enumtest(p);

}

fn enumtest(x: Message){
    match x {
        Message::Quit => println!("Quit"),
        Message::ChangeColor(r,g,b) => println!("ChangeColor r = {}, g = {}, b = {}", r,g,b),
        Message::Move{x,y} => println!("x = {}, y = {}",x,y),
        Message::Write(s) => println!("The passed string is {}",s),
    };

}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// Implement ncurses-compatible database discovery
/// Does not support hashed database, only filesystem!

use std::io::File;
use std::os::getenv;
use std::{os, str};

/// Return path to database entry for `term`
pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
    if term.len() == 0 {
        return None;
    }

    let homedir = os::homedir();

    let mut dirs_to_search = ~[];
    let first_char = term.char_at(0);

    // Find search directory
    match getenv("TERMINFO") {
        Some(dir) => dirs_to_search.push(Path::new(dir)),
        None => {
            if homedir.is_some() {
                // ncurses compatability;
                dirs_to_search.push(homedir.unwrap().join(".terminfo"))
            }
            match getenv("TERMINFO_DIRS") {
                Some(dirs) => for i in dirs.split(':') {
                    if i == "" {
                        dirs_to_search.push(Path::new("/usr/share/terminfo"));
                    } else {
                        dirs_to_search.push(Path::new(i.to_owned()));
                    }
                },
                // Found nothing, use the default paths
                // /usr/share/terminfo is the de facto location, but it seems
                // Ubuntu puts it in /lib/terminfo
                None => {
                    dirs_to_search.push(Path::new("/usr/share/terminfo"));
                    dirs_to_search.push(Path::new("/lib/terminfo"));
                }
            }
        }
    };

    // Look for the terminal in all of the search directories
    for p in dirs_to_search.iter() {
        if p.exists() {
            let f = str::from_char(first_char);
            let newp = p.join_many([f.as_slice(), term]);
            if newp.exists() {
                return Some(~newp);
            }
            // on some installations the dir is named after the hex of the char (e.g. OS X)
            let f = format!("{:x}", first_char as uint);
            let newp = p.join_many([f.as_slice(), term]);
            if newp.exists() {
                return Some(~newp);
            }
        }
    }
    None
}

/// Return open file for `term`
pub fn open(term: &str) -> Result<File, ~str> {
    match get_dbpath_for_term(term) {
        Some(x) => {
            match File::open(x) {
                Ok(file) => Ok(file),
                Err(e) => Err(format!("error opening file: {}", e)),
            }
        }
        None => Err(format!("could not find terminfo entry for {}", term))
    }
}

#[test]
#[ignore(reason = "buildbots don't have ncurses installed and I can't mock everything I need")]
fn test_get_dbpath_for_term() {
    // woefully inadequate test coverage
    // note: current tests won't work with non-standard terminfo hierarchies (e.g. OS X's)
    use std::os::{setenv, unsetenv};
    // FIXME (#9639): This needs to handle non-utf8 paths
    fn x(t: &str) -> ~str {
        let p = get_dbpath_for_term(t).expect("no terminfo entry found");
        p.as_str().unwrap().to_owned()
    };
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    assert!(get_dbpath_for_term("") == None);
    setenv("TERMINFO_DIRS", ":");
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    unsetenv("TERMINFO_DIRS");
}

#[test]
#[ignore(reason = "see test_get_dbpath_for_term")]
fn test_open() {
    open("screen").unwrap();
    let t = open("nonexistent terminal that hopefully does not exist");
    assert!(t.is_err());
}
<commit_msg>auto merge of #12656 : Armavica/rust/terminfo, r=sfackler<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// Implement ncurses-compatible database discovery
/// Does not support hashed database, only filesystem!

use std::io::File;
use std::os::getenv;
use std::{os, str};

/// Return path to database entry for `term`
pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
    if term.len() == 0 {
        return None;
    }

    let homedir = os::homedir();

    let mut dirs_to_search = ~[];
    let first_char = term.char_at(0);

    // Find search directory
    match getenv("TERMINFO") {
        Some(dir) => dirs_to_search.push(Path::new(dir)),
        None => {
            if homedir.is_some() {
                // ncurses compatability;
                dirs_to_search.push(homedir.unwrap().join(".terminfo"))
            }
            match getenv("TERMINFO_DIRS") {
                Some(dirs) => for i in dirs.split(':') {
                    if i == "" {
                        dirs_to_search.push(Path::new("/usr/share/terminfo"));
                    } else {
                        dirs_to_search.push(Path::new(i.to_owned()));
                    }
                },
                // Found nothing in TERMINFO_DIRS, use the default paths:
                // According to  /etc/terminfo/README, after looking at
                // ~/.terminfo, ncurses will search /etc/terminfo, then
                // /lib/terminfo, and eventually /usr/share/terminfo.
                None => {
                    dirs_to_search.push(Path::new("/etc/terminfo"));
                    dirs_to_search.push(Path::new("/lib/terminfo"));
                    dirs_to_search.push(Path::new("/usr/share/terminfo"));
                }
            }
        }
    };

    // Look for the terminal in all of the search directories
    for p in dirs_to_search.iter() {
        if p.exists() {
            let f = str::from_char(first_char);
            let newp = p.join_many([f.as_slice(), term]);
            if newp.exists() {
                return Some(~newp);
            }
            // on some installations the dir is named after the hex of the char (e.g. OS X)
            let f = format!("{:x}", first_char as uint);
            let newp = p.join_many([f.as_slice(), term]);
            if newp.exists() {
                return Some(~newp);
            }
        }
    }
    None
}

/// Return open file for `term`
pub fn open(term: &str) -> Result<File, ~str> {
    match get_dbpath_for_term(term) {
        Some(x) => {
            match File::open(x) {
                Ok(file) => Ok(file),
                Err(e) => Err(format!("error opening file: {}", e)),
            }
        }
        None => Err(format!("could not find terminfo entry for {}", term))
    }
}

#[test]
#[ignore(reason = "buildbots don't have ncurses installed and I can't mock everything I need")]
fn test_get_dbpath_for_term() {
    // woefully inadequate test coverage
    // note: current tests won't work with non-standard terminfo hierarchies (e.g. OS X's)
    use std::os::{setenv, unsetenv};
    // FIXME (#9639): This needs to handle non-utf8 paths
    fn x(t: &str) -> ~str {
        let p = get_dbpath_for_term(t).expect("no terminfo entry found");
        p.as_str().unwrap().to_owned()
    };
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    assert!(get_dbpath_for_term("") == None);
    setenv("TERMINFO_DIRS", ":");
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    unsetenv("TERMINFO_DIRS");
}

#[test]
#[ignore(reason = "see test_get_dbpath_for_term")]
fn test_open() {
    open("screen").unwrap();
    let t = open("nonexistent terminal that hopefully does not exist");
    assert!(t.is_err());
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Visualize_a_tree

extern crate rand;
extern crate rustc_serialize;
extern crate term_painter;

use rand::Rng;
use rustc_serialize::json;
use std::cmp::Ordering;
use std::env;
use std::fmt::{Debug, Display, Formatter, Result};
use term_painter::ToStyle;
use term_painter::Color::*;

type NodePtr = Option<usize>;

#[derive(Debug, PartialEq, Clone, Copy)]
enum Side {
    Left,
    Right,
    Up,
}

#[derive(Debug, PartialEq, Clone, Copy)]
enum DisplayElement {
    TrunkSpace,
    SpaceLeft,
    SpaceRight,
    SpaceSpace,
    Root,
}

impl DisplayElement {
    fn string(&self) -> String {
        match *self {
            DisplayElement::TrunkSpace => "    │   ".to_string(),
            DisplayElement::SpaceRight => "    ┌───".to_string(),
            DisplayElement::SpaceLeft => "    └───".to_string(),
            DisplayElement::SpaceSpace => "        ".to_string(),
            DisplayElement::Root => "├──".to_string(),
        }
    }
}

#[derive(Debug, Clone, Copy, RustcDecodable, RustcEncodable)]
struct Node<K, V> {
    key: K,
    value: V,
    left: NodePtr,
    right: NodePtr,
    up: NodePtr,
}

impl<K: Ord + Copy, V: Copy> Node<K, V> {
    pub fn new(k: K, v: V) -> Node<K, V> {
        Node {
            key: k,
            value: v,
            left: None,
            right: None,
            up: None,
        }
    }

    pub fn set_ptr(&mut self, side: Side, to: NodePtr) {
        let field = match side {
            Side::Up => &mut self.up,
            Side::Left => &mut self.left,
            _ => &mut self.right,
        };
        *field = to;
    }

    pub fn get_ptr(&self, side: Side) -> NodePtr {
        match side {
            Side::Up => self.up,
            Side::Left => self.left,
            _ => self.right,
        }
    }
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
struct Tree<K, V> {
    root: NodePtr,
    store: Vec<Node<K, V>>,
}

impl<K: Ord + Copy + Debug + Display, V: Debug + Copy + Display> Tree<K, V> {
    pub fn get_node(&self, np: NodePtr) -> Node<K, V> {
        assert!(np.is_some());
        self.store[np.unwrap()]
    }

    pub fn get_key(&self, np: NodePtr) -> K {
        assert!(np.is_some());
        self.store[np.unwrap()].key
    }

    pub fn _get_value(&self, np: NodePtr) -> V {
        assert!(np.is_some());
        self.store[np.unwrap()].value
    }

    pub fn get_pointer(&self, np: NodePtr, side: Side) -> NodePtr {
        assert!(np.is_some());
        self.store[np.unwrap()].get_ptr(side)
    }

    pub fn set_pointer(&mut self, np: NodePtr, side: Side, to: NodePtr) {
        assert!(np.is_some());
        self.store[np.unwrap()].set_ptr(side, to);
    }

    pub fn new() -> Self {
        Tree {
            root: None,
            store: Vec::<Node<K, V>>::with_capacity(128),
        }
    }

    pub fn insert(&mut self, k: K, v: V) -> Option<Node<K, V>> {
        let mut n = Node::new(k, v);

        if self.root.is_none() {
            assert!(self.store.len() == 0);
            self.store.push(n);
            self.root = Some(0);
            return Some(n);
        }

        let mut p = self.root;      // Possibly None
        let mut prev = p;
        let mut side = Side::Left;
        while let Some(_) = p {
            prev = p;
            match n.key.cmp(&self.get_key(p)) {
                Ordering::Less => {
                    side = Side::Left;
                    p = self.get_pointer(p, side);
                }
                Ordering::Greater => {
                    side = Side::Right;
                    p = self.get_pointer(p, side);
                }
                Ordering::Equal => {
                    // Key exists
                    return None;
                }
            }
        }
        // Set child's pointer
        n.up = prev;
        // Stow the node
        self.store.push(n);
        // Set parent's pointer
        let ptr = Some(self.store.len() - 1);
        self.set_pointer(prev, side, ptr);
        Some(n)
    }

    // Prints the tree with root p.  The idea is to do an in-order traversal
    // (reverse in-order in this case, where right is on top), and print nodes as they
    // are visited, one per line. Each invocation of display() gets its own copy
    // of the display element vector e, which is grown with either whitespace or
    // a trunk element, then modified in its last and possibly second-to-last
    // characters in context.
    fn display(&self, p: NodePtr, side: Side, e: &Vec<DisplayElement>, f: &mut Formatter) {
        if p.is_none() {
            return;
        }

        let mut elems = e.clone();
        let node = self.get_node(p);
        let mut tail = DisplayElement::SpaceSpace;
        if node.up != self.root {
            // If the direction is switching, I need the trunk element to appear in the lines
            // printed before that node is visited.
            if side == Side::Left && node.right.is_some() {
                elems.push(DisplayElement::TrunkSpace);
            } else {
                elems.push(DisplayElement::SpaceSpace);
            }
        }
        let hindex = elems.len() - 1;
        self.display(node.right, Side::Right, &elems, f);

        if p == self.root {
            elems[hindex] = DisplayElement::Root;
            tail = DisplayElement::TrunkSpace;
        } else if side == Side::Right {
            // Right subtree finished
            elems[hindex] = DisplayElement::SpaceRight;
            // Prepare trunk element in case there is a left subtree
            tail = DisplayElement::TrunkSpace;
        } else if side == Side::Left {
            elems[hindex] = DisplayElement::SpaceLeft;
            let parent = self.get_node(node.up);
            if parent.up.is_some() && self.get_pointer(parent.up, Side::Right) == node.up {
                // Direction switched, need trunk element starting with this node/line
                elems[hindex - 1] = DisplayElement::TrunkSpace;
            }
        }

        // Visit node => print accumulated elements. Each node gets a line and each line gets a
        // node.
        for e in elems.clone() {
            let _ = write!(f, "{}", e.string());
        }
        let _ = write!(f,
                       "{key:>width$} ",
                       key = Green.bold().paint(node.key),
                       width = 2);
        let _ = write!(f,
                       "{value:>width$}\n",
                       value = Blue.bold().paint(format!("{:.*}", 2, node.value)),
                       width = 4);

        // Overwrite last element before continuing traversal
        elems[hindex] = tail;

        self.display(node.left, Side::Left, &elems, f);
    }
}

impl<K: Ord + Copy + Debug + Display, V: Debug + Copy + Display> Display for Tree<K, V> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        if self.root.is_none() {
            write!(f, "[empty]")
        } else {
            let mut v: Vec<DisplayElement> = Vec::new();
            self.display(self.root, Side::Up, &mut v, f);
            Ok(())
        }
    }
}

fn random_tree(n: u32) -> Tree<i32, f32> {
    let mut tree: Tree<i32, f32> = Tree::new();
    let mut rng = rand::thread_rng();
    tree.insert(0, rng.gen_range(-1f32, 1f32));
    for _ in 0..n - 1 {
        tree.insert(rng.gen_range(-(n as i32) / 2, (n as i32) / 2),
                    rng.gen_range(-1f32, 1f32));
    }
    tree
}

/// Prints json representation of tree as well, useful for shorter code listings.
fn main() {
    let args: Vec<String> = env::args().collect();
    let mut r_nodes: u32 = 20;

    match args.len() {
        1 => {}
        2 => {
            r_nodes = args[1].parse::<u32>().unwrap();
        }
        _ => {
            println!("visualize_a_tree <no. of nodes>");
            return;
        }
    }

    let tree = random_tree(r_nodes);
    let encoded = json::encode(&tree).unwrap();

    println!("{}", tree);
    println!("{}", encoded);

    println!("\nCanned tree, decoded:");
    _main_for_rosetta()
}

/// Decodes and prints a previously generated tree.  Presenting this with display(), the fmt()
/// overload, and the struct & enum definitions is sufficient for this demonstration.
fn _main_for_rosetta() {
    let encoded = r#"{"root":0,"store":[{"key":0,"value":0.45,"left":1,"right":3,
        "up":null},{"key":-8,"value":-0.94,"left":7,"right":2,"up":0}, {"key":-1,
        "value":0.15,"left":8,"right":null,"up":1},{"key":7, "value":-0.29,"left":4,
        "right":9,"up":0},{"key":5,"value":0.80,"left":5,"right":null,"up":3},
        {"key":4,"value":-0.85,"left":6,"right":null,"up":4},{"key":3,"value":-0.46,
        "left":null,"right":null,"up":5},{"key":-10,"value":-0.85,"left":null,
        "right":13,"up":1},{"key":-6,"value":-0.42,"left":null,"right":10,"up":2},
        {"key":9,"value":0.63,"left":12,"right":null,"up":3},{"key":-3,"value":-0.83,
        "left":null,"right":11,"up":8},{"key":-2,"value":0.75,"left":null,"right":null,
        "up":10},{"key":8,"value":-0.48,"left":null,"right":null,"up":9},{"key":-9,
        "value":0.53,"left":null,"right":null,"up":7}]}"#;
    let tree: Tree<i32, f32> = json::decode(encoded).unwrap();
    println!("{}", tree);
}

#[cfg(test)]
mod tests {
    use super::{Side, Tree};
    use random_tree;
    use rustc_serialize::json;

    #[test]
    fn test_insert() {
        let mut tree: Tree<i32, f32> = Tree::new();
        tree.insert(0, 0.0);
        tree.insert(8, 8.8);
        tree.insert(-8, -8.8);
        assert!(tree.insert(4, 4.4).is_some());
        tree.insert(12, 12.12);

        assert_eq!(tree._get_value(tree.get_pointer(tree.root, Side::Left)),
                   -8.8);
        assert_eq!(tree._get_value(tree.get_pointer(tree.get_pointer(tree.root, Side::Right),
                                                    Side::Right)),
                   12.12);
        assert_eq!(tree.get_pointer(tree.get_pointer(tree.get_pointer(tree.root, Side::Right),
                                                     Side::Right),
                                    Side::Left),
                   None);

        tree = random_tree(100);
        assert!(tree.store.len() > 0);
    }

    #[test]
    fn test_decode() {
        let encoded = r#"{"root":0,"store":[{"key":0,"value":0.45,"left":1,"right":3,
            "up":null},{"key":-8,"value":-0.94,"left":7,"right":2,"up":0}, {"key":-1,
            "value":0.15,"left":8,"right":null,"up":1},{"key":7, "value":-0.29,"left":4,
            "right":9,"up":0},{"key":5,"value":0.80,"left":5,"right":null,"up":3},
            {"key":4,"value":-0.85,"left":6,"right":null,"up":4},{"key":3,"value":-0.46,
            "left":null,"right":null,"up":5},{"key":-10,"value":-0.85,"left":null,
            "right":13,"up":1},{"key":-6,"value":-0.42,"left":null,"right":10,"up":2},
            {"key":9,"value":0.63,"left":12,"right":null,"up":3},{"key":-3,"value":-0.83,
            "left":null,"right":11,"up":8},{"key":-2,"value":0.75,"left":null,"right":null,
            "up":10},{"key":8,"value":-0.48,"left":null,"right":null,"up":9},{"key":-9,
            "value":0.53,"left":null,"right":null,"up":7}]}"#;
        let tree: Tree<i32, f32> = json::decode(&encoded).unwrap();
        assert_eq!(tree.root, Some(0));
        assert_eq!(tree.store[4].key, 5);
        assert_eq!(tree.store[4].value, 0.80);
        assert_eq!(tree.store[4].right, None);
        assert_eq!(tree.store[12].up, Some(9));
        assert_eq!(tree.store[9].left, Some(12));
    }
}
<commit_msg>remove needless mutability<commit_after>// http://rosettacode.org/wiki/Visualize_a_tree

extern crate rand;
extern crate rustc_serialize;
extern crate term_painter;

use rand::Rng;
use rustc_serialize::json;
use std::cmp::Ordering;
use std::env;
use std::fmt::{Debug, Display, Formatter, Result};
use term_painter::ToStyle;
use term_painter::Color::*;

type NodePtr = Option<usize>;

#[derive(Debug, PartialEq, Clone, Copy)]
enum Side {
    Left,
    Right,
    Up,
}

#[derive(Debug, PartialEq, Clone, Copy)]
enum DisplayElement {
    TrunkSpace,
    SpaceLeft,
    SpaceRight,
    SpaceSpace,
    Root,
}

impl DisplayElement {
    fn string(&self) -> String {
        match *self {
            DisplayElement::TrunkSpace => "    │   ".to_string(),
            DisplayElement::SpaceRight => "    ┌───".to_string(),
            DisplayElement::SpaceLeft => "    └───".to_string(),
            DisplayElement::SpaceSpace => "        ".to_string(),
            DisplayElement::Root => "├──".to_string(),
        }
    }
}

#[derive(Debug, Clone, Copy, RustcDecodable, RustcEncodable)]
struct Node<K, V> {
    key: K,
    value: V,
    left: NodePtr,
    right: NodePtr,
    up: NodePtr,
}

impl<K: Ord + Copy, V: Copy> Node<K, V> {
    pub fn new(k: K, v: V) -> Node<K, V> {
        Node {
            key: k,
            value: v,
            left: None,
            right: None,
            up: None,
        }
    }

    pub fn set_ptr(&mut self, side: Side, to: NodePtr) {
        let field = match side {
            Side::Up => &mut self.up,
            Side::Left => &mut self.left,
            _ => &mut self.right,
        };
        *field = to;
    }

    pub fn get_ptr(&self, side: Side) -> NodePtr {
        match side {
            Side::Up => self.up,
            Side::Left => self.left,
            _ => self.right,
        }
    }
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
struct Tree<K, V> {
    root: NodePtr,
    store: Vec<Node<K, V>>,
}

impl<K: Ord + Copy + Debug + Display, V: Debug + Copy + Display> Tree<K, V> {
    pub fn get_node(&self, np: NodePtr) -> Node<K, V> {
        assert!(np.is_some());
        self.store[np.unwrap()]
    }

    pub fn get_key(&self, np: NodePtr) -> K {
        assert!(np.is_some());
        self.store[np.unwrap()].key
    }

    pub fn _get_value(&self, np: NodePtr) -> V {
        assert!(np.is_some());
        self.store[np.unwrap()].value
    }

    pub fn get_pointer(&self, np: NodePtr, side: Side) -> NodePtr {
        assert!(np.is_some());
        self.store[np.unwrap()].get_ptr(side)
    }

    pub fn set_pointer(&mut self, np: NodePtr, side: Side, to: NodePtr) {
        assert!(np.is_some());
        self.store[np.unwrap()].set_ptr(side, to);
    }

    pub fn new() -> Self {
        Tree {
            root: None,
            store: Vec::<Node<K, V>>::with_capacity(128),
        }
    }

    pub fn insert(&mut self, k: K, v: V) -> Option<Node<K, V>> {
        let mut n = Node::new(k, v);

        if self.root.is_none() {
            assert!(self.store.len() == 0);
            self.store.push(n);
            self.root = Some(0);
            return Some(n);
        }

        let mut p = self.root;      // Possibly None
        let mut prev = p;
        let mut side = Side::Left;
        while let Some(_) = p {
            prev = p;
            match n.key.cmp(&self.get_key(p)) {
                Ordering::Less => {
                    side = Side::Left;
                    p = self.get_pointer(p, side);
                }
                Ordering::Greater => {
                    side = Side::Right;
                    p = self.get_pointer(p, side);
                }
                Ordering::Equal => {
                    // Key exists
                    return None;
                }
            }
        }
        // Set child's pointer
        n.up = prev;
        // Stow the node
        self.store.push(n);
        // Set parent's pointer
        let ptr = Some(self.store.len() - 1);
        self.set_pointer(prev, side, ptr);
        Some(n)
    }

    // Prints the tree with root p.  The idea is to do an in-order traversal
    // (reverse in-order in this case, where right is on top), and print nodes as they
    // are visited, one per line. Each invocation of display() gets its own copy
    // of the display element vector e, which is grown with either whitespace or
    // a trunk element, then modified in its last and possibly second-to-last
    // characters in context.
    fn display(&self, p: NodePtr, side: Side, e: &Vec<DisplayElement>, f: &mut Formatter) {
        if p.is_none() {
            return;
        }

        let mut elems = e.clone();
        let node = self.get_node(p);
        let mut tail = DisplayElement::SpaceSpace;
        if node.up != self.root {
            // If the direction is switching, I need the trunk element to appear in the lines
            // printed before that node is visited.
            if side == Side::Left && node.right.is_some() {
                elems.push(DisplayElement::TrunkSpace);
            } else {
                elems.push(DisplayElement::SpaceSpace);
            }
        }
        let hindex = elems.len() - 1;
        self.display(node.right, Side::Right, &elems, f);

        if p == self.root {
            elems[hindex] = DisplayElement::Root;
            tail = DisplayElement::TrunkSpace;
        } else if side == Side::Right {
            // Right subtree finished
            elems[hindex] = DisplayElement::SpaceRight;
            // Prepare trunk element in case there is a left subtree
            tail = DisplayElement::TrunkSpace;
        } else if side == Side::Left {
            elems[hindex] = DisplayElement::SpaceLeft;
            let parent = self.get_node(node.up);
            if parent.up.is_some() && self.get_pointer(parent.up, Side::Right) == node.up {
                // Direction switched, need trunk element starting with this node/line
                elems[hindex - 1] = DisplayElement::TrunkSpace;
            }
        }

        // Visit node => print accumulated elements. Each node gets a line and each line gets a
        // node.
        for e in elems.clone() {
            let _ = write!(f, "{}", e.string());
        }
        let _ = write!(f,
                       "{key:>width$} ",
                       key = Green.bold().paint(node.key),
                       width = 2);
        let _ = write!(f,
                       "{value:>width$}\n",
                       value = Blue.bold().paint(format!("{:.*}", 2, node.value)),
                       width = 4);

        // Overwrite last element before continuing traversal
        elems[hindex] = tail;

        self.display(node.left, Side::Left, &elems, f);
    }
}

impl<K: Ord + Copy + Debug + Display, V: Debug + Copy + Display> Display for Tree<K, V> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        if self.root.is_none() {
            write!(f, "[empty]")
        } else {
            let mut v: Vec<DisplayElement> = Vec::new();
            self.display(self.root, Side::Up, &v, f);
            Ok(())
        }
    }
}

fn random_tree(n: u32) -> Tree<i32, f32> {
    let mut tree: Tree<i32, f32> = Tree::new();
    let mut rng = rand::thread_rng();
    tree.insert(0, rng.gen_range(-1f32, 1f32));
    for _ in 0..n - 1 {
        tree.insert(rng.gen_range(-(n as i32) / 2, (n as i32) / 2),
                    rng.gen_range(-1f32, 1f32));
    }
    tree
}

/// Prints json representation of tree as well, useful for shorter code listings.
fn main() {
    let args: Vec<String> = env::args().collect();
    let mut r_nodes: u32 = 20;

    match args.len() {
        1 => {}
        2 => {
            r_nodes = args[1].parse::<u32>().unwrap();
        }
        _ => {
            println!("visualize_a_tree <no. of nodes>");
            return;
        }
    }

    let tree = random_tree(r_nodes);
    let encoded = json::encode(&tree).unwrap();

    println!("{}", tree);
    println!("{}", encoded);

    println!("\nCanned tree, decoded:");
    _main_for_rosetta()
}

/// Decodes and prints a previously generated tree.  Presenting this with display(), the fmt()
/// overload, and the struct & enum definitions is sufficient for this demonstration.
fn _main_for_rosetta() {
    let encoded = r#"{"root":0,"store":[{"key":0,"value":0.45,"left":1,"right":3,
        "up":null},{"key":-8,"value":-0.94,"left":7,"right":2,"up":0}, {"key":-1,
        "value":0.15,"left":8,"right":null,"up":1},{"key":7, "value":-0.29,"left":4,
        "right":9,"up":0},{"key":5,"value":0.80,"left":5,"right":null,"up":3},
        {"key":4,"value":-0.85,"left":6,"right":null,"up":4},{"key":3,"value":-0.46,
        "left":null,"right":null,"up":5},{"key":-10,"value":-0.85,"left":null,
        "right":13,"up":1},{"key":-6,"value":-0.42,"left":null,"right":10,"up":2},
        {"key":9,"value":0.63,"left":12,"right":null,"up":3},{"key":-3,"value":-0.83,
        "left":null,"right":11,"up":8},{"key":-2,"value":0.75,"left":null,"right":null,
        "up":10},{"key":8,"value":-0.48,"left":null,"right":null,"up":9},{"key":-9,
        "value":0.53,"left":null,"right":null,"up":7}]}"#;
    let tree: Tree<i32, f32> = json::decode(encoded).unwrap();
    println!("{}", tree);
}

#[cfg(test)]
mod tests {
    use super::{Side, Tree};
    use random_tree;
    use rustc_serialize::json;

    #[test]
    fn test_insert() {
        let mut tree: Tree<i32, f32> = Tree::new();
        tree.insert(0, 0.0);
        tree.insert(8, 8.8);
        tree.insert(-8, -8.8);
        assert!(tree.insert(4, 4.4).is_some());
        tree.insert(12, 12.12);

        assert_eq!(tree._get_value(tree.get_pointer(tree.root, Side::Left)),
                   -8.8);
        assert_eq!(tree._get_value(tree.get_pointer(tree.get_pointer(tree.root, Side::Right),
                                                    Side::Right)),
                   12.12);
        assert_eq!(tree.get_pointer(tree.get_pointer(tree.get_pointer(tree.root, Side::Right),
                                                     Side::Right),
                                    Side::Left),
                   None);

        tree = random_tree(100);
        assert!(tree.store.len() > 0);
    }

    #[test]
    fn test_decode() {
        let encoded = r#"{"root":0,"store":[{"key":0,"value":0.45,"left":1,"right":3,
            "up":null},{"key":-8,"value":-0.94,"left":7,"right":2,"up":0}, {"key":-1,
            "value":0.15,"left":8,"right":null,"up":1},{"key":7, "value":-0.29,"left":4,
            "right":9,"up":0},{"key":5,"value":0.80,"left":5,"right":null,"up":3},
            {"key":4,"value":-0.85,"left":6,"right":null,"up":4},{"key":3,"value":-0.46,
            "left":null,"right":null,"up":5},{"key":-10,"value":-0.85,"left":null,
            "right":13,"up":1},{"key":-6,"value":-0.42,"left":null,"right":10,"up":2},
            {"key":9,"value":0.63,"left":12,"right":null,"up":3},{"key":-3,"value":-0.83,
            "left":null,"right":11,"up":8},{"key":-2,"value":0.75,"left":null,"right":null,
            "up":10},{"key":8,"value":-0.48,"left":null,"right":null,"up":9},{"key":-9,
            "value":0.53,"left":null,"right":null,"up":7}]}"#;
        let tree: Tree<i32, f32> = json::decode(&encoded).unwrap();
        assert_eq!(tree.root, Some(0));
        assert_eq!(tree.store[4].key, 5);
        assert_eq!(tree.store[4].value, 0.80);
        assert_eq!(tree.store[4].right, None);
        assert_eq!(tree.store[12].up, Some(9));
        assert_eq!(tree.store[9].left, Some(12));
    }
}
<|endoftext|>


<commit_before>use webcore::value::{Value, Reference};
use webcore::try_from::TryInto;
use webcore::reference_type::ReferenceType;
use webapi::node::Node;

/// `NodeList` objects are collections of nodes such as those returned by properties
/// such as [INode::child_nodes](trait.INode.html#method.child_nodes) and the
/// [Document::query_selector_all](struct.Document.html#method.query_selector_all) method.
///
/// In some cases, the `NodeList` is a live collection, which means that changes in the DOM
/// are reflected in the collection - for example [INode::child_nodes](trait.INode.html#method.child_nodes) is live.
///
/// In other cases, the `NodeList` is a static collection, meaning any subsequent change
/// in the DOM does not affect the content of the collection - for example
/// [Document::query_selector_all](struct.Document.html#method.query_selector_all) returns
/// a static `NodeList`.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/NodeList)
// https://dom.spec.whatwg.org/#nodelist
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "NodeList")]
pub struct NodeList( Reference );

impl NodeList {
    /// Returns the number of [Node](struct.Node.html)s contained in this list.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/NodeList/length)
    // https://dom.spec.whatwg.org/#ref-for-dom-nodelist-length
    pub fn len( &self ) -> u32 {
        js!( return @{self}.length; ).try_into().unwrap()
    }

    /// Returns an iterator over the list.
    pub fn iter( &self ) -> NodeIter {
        NodeIter {
            list: self.clone(),
            index: 0
        }
    }
}

impl IntoIterator for NodeList {
    type Item = Node;
    type IntoIter = NodeIter;

    #[inline]
    fn into_iter( self ) -> Self::IntoIter {
        NodeIter {
            list: self,
            index: 0
        }
    }
}

impl< 'a > IntoIterator for &'a NodeList {
    type Item = Node;
    type IntoIter = NodeIter;

    #[inline]
    fn into_iter( self ) -> Self::IntoIter {
        NodeIter {
            list: self.clone(),
            index: 0
        }
    }
}

#[derive(Debug)]
pub struct NodeIter {
    list: NodeList,
    index: i32
}

impl Iterator for NodeIter {
    type Item = Node;
    fn next( &mut self ) -> Option< Self::Item > {
        let value = js!(
            return @{&self.list}[ @{self.index} ];
        );

        let node = match value {
            Value::Undefined => return None,
            Value::Reference( reference ) => unsafe { Node::from_reference_unchecked( reference ) },
            _ => unreachable!()
        };

        self.index += 1;
        Some( node )
    }
}
<commit_msg>Add `NodeList::item` (#172)<commit_after>use webcore::value::{Value, Reference};
use webcore::try_from::TryInto;
use webcore::reference_type::ReferenceType;
use webapi::node::Node;

/// `NodeList` objects are collections of nodes such as those returned by properties
/// such as [INode::child_nodes](trait.INode.html#method.child_nodes) and the
/// [Document::query_selector_all](struct.Document.html#method.query_selector_all) method.
///
/// In some cases, the `NodeList` is a live collection, which means that changes in the DOM
/// are reflected in the collection - for example [INode::child_nodes](trait.INode.html#method.child_nodes) is live.
///
/// In other cases, the `NodeList` is a static collection, meaning any subsequent change
/// in the DOM does not affect the content of the collection - for example
/// [Document::query_selector_all](struct.Document.html#method.query_selector_all) returns
/// a static `NodeList`.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/NodeList)
// https://dom.spec.whatwg.org/#nodelist
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "NodeList")]
pub struct NodeList( Reference );

impl NodeList {
    /// Returns the number of [Node](struct.Node.html)s contained in this list.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/NodeList/length)
    // https://dom.spec.whatwg.org/#ref-for-dom-nodelist-length
    pub fn len( &self ) -> u32 {
        js!( return @{self}.length; ).try_into().unwrap()
    }

    /// Returns a node from a NodeList by index.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/NodeList/item)
    // https://dom.spec.whatwg.org/#ref-for-dom-nodelist-item
    pub fn item( &self, index: u32 ) -> Option< Node > {
        js!(
            return @{self}[ @{index} ];
        ).try_into().unwrap()
    }

    /// Returns an iterator over the list.
    pub fn iter( &self ) -> NodeIter {
        NodeIter {
            list: self.clone(),
            index: 0
        }
    }
}

impl IntoIterator for NodeList {
    type Item = Node;
    type IntoIter = NodeIter;

    #[inline]
    fn into_iter( self ) -> Self::IntoIter {
        NodeIter {
            list: self,
            index: 0
        }
    }
}

impl< 'a > IntoIterator for &'a NodeList {
    type Item = Node;
    type IntoIter = NodeIter;

    #[inline]
    fn into_iter( self ) -> Self::IntoIter {
        NodeIter {
            list: self.clone(),
            index: 0
        }
    }
}

#[derive(Debug)]
pub struct NodeIter {
    list: NodeList,
    index: i32
}

impl Iterator for NodeIter {
    type Item = Node;
    fn next( &mut self ) -> Option< Self::Item > {
        let value = js!(
            return @{&self.list}[ @{self.index} ];
        );

        let node = match value {
            Value::Undefined => return None,
            Value::Reference( reference ) => unsafe { Node::from_reference_unchecked( reference ) },
            _ => unreachable!()
        };

        self.index += 1;
        Some( node )
    }
}
<|endoftext|>


<commit_before>/// Attempt to construct Self via a conversion.
///
/// This definition is only temporary until Rust's `TryFrom` is stabilized.
pub trait TryFrom< T >: Sized {
    /// The type returned in the event of a conversion error.
    type Error;

    /// Performs the conversion.
    fn try_from( T ) -> Result< Self, Self::Error >;
}

/// An attempted conversion that consumes self, which may or may not be expensive.
///
/// his definition is only temporary until Rust's `TryInto` is stabilized.
pub trait TryInto< T >: Sized {
    /// The type returned in the event of a conversion error.
    type Error;

    /// Performs the conversion.
    fn try_into( self ) -> Result< T, Self::Error >;
}

impl< T, U > TryInto< U > for T where U: TryFrom< T > {
    type Error = U::Error;
    #[inline]
    fn try_into( self ) -> Result< U, U::Error > {
        U::try_from( self )
    }
}
<commit_msg>Fix a typo<commit_after>/// Attempt to construct Self via a conversion.
///
/// This definition is only temporary until Rust's `TryFrom` is stabilized.
pub trait TryFrom< T >: Sized {
    /// The type returned in the event of a conversion error.
    type Error;

    /// Performs the conversion.
    fn try_from( T ) -> Result< Self, Self::Error >;
}

/// An attempted conversion that consumes self, which may or may not be expensive.
///
/// This definition is only temporary until Rust's `TryInto` is stabilized.
pub trait TryInto< T >: Sized {
    /// The type returned in the event of a conversion error.
    type Error;

    /// Performs the conversion.
    fn try_into( self ) -> Result< T, Self::Error >;
}

impl< T, U > TryInto< U > for T where U: TryFrom< T > {
    type Error = U::Error;
    #[inline]
    fn try_into( self ) -> Result< U, U::Error > {
        U::try_from( self )
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::sync::Arc;
use error::*;
use eval::Env;
use itertools::Itertools;
use std::fmt;
use token::Literal;

#[derive(Clone, Debug)]
pub enum Expr {
    Nil,
    Func(Arc<Function>),
    Atom(Atom),
    List(List),
    Vector(Vector),
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum Atom {
    Bool(bool),
    Int(i64),
    Flt(f64),
    Str(String),
    Sym(Symbol),
}

#[derive(Clone, Debug)]
pub struct List(pub Vec<Expr>);

#[derive(Clone, Debug)]
pub struct Vector(pub Vec<Expr>);

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Symbol(pub String);

pub enum Function {
    Builtin { name: String, func: Lambda },
    User {
        name: Option<String>,
        params: Vec<Symbol>,
        body: Vec<Expr>,
    },
}

pub type Lambda = fn(&[Expr], &Env) -> Result<Expr>;

impl Expr {
    pub fn atom(&self) -> Option<&Atom> {
        if let &Expr::Atom(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn list(&self) -> Option<&List> {
        if let &Expr::List(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn vector(&self) -> Option<&Vector> {
        if let &Expr::Vector(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn func(&self) -> Option<&Function> {
        if let &Expr::Func(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn sym(&self) -> Option<&Symbol> {
        self.atom().and_then(|a| a.sym())
    }

    pub fn truthiness(&self) -> bool {
        match self {
            &Expr::Nil => false,
            &Expr::Atom(ref a) => {
                match a {
                    &Atom::Bool(b) => b,
                    _ => true,
                }
            }
            _ => true,
        }
    }
}

impl Atom {
    pub fn is_boolean(&self) -> bool {
        self.boolean().is_some()
    }

    pub fn is_int(&self) -> bool {
        self.int().is_some()
    }

    pub fn is_flt(&self) -> bool {
        self.flt().is_some()
    }

    pub fn is_str(&self) -> bool {
        self.str().is_some()
    }

    pub fn is_num(&self) -> bool {
        match self {
            &Atom::Flt(_) | &Atom::Int(_) => true,
            _ => false,
        }
    }

    pub fn boolean(&self) -> Option<bool> {
        if let &Atom::Bool(x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn int(&self) -> Option<i64> {
        if let &Atom::Int(x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn flt(&self) -> Option<f64> {
        if let &Atom::Flt(x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn str(&self) -> Option<&str> {
        if let &Atom::Str(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn sym(&self) -> Option<&Symbol> {
        if let &Atom::Sym(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn map_int<A, F>(self, f: F) -> Atom
    where
        F: FnOnce(i64) -> A,
        A: Into<Atom>,
    {
        match self {
            Atom::Int(int) => f(int).into(),
            _ => self,
        }
    }

    pub fn map_flt<A, F>(self, f: F) -> Atom
    where
        F: FnOnce(f64) -> A,
        A: Into<Atom>,
    {
        match self {
            Atom::Flt(flt) => f(flt).into(),
            _ => self,
        }
    }
}

impl Function {
    pub fn builtin<S>(name: S, func: Lambda) -> Self
    where
        S: Into<String>,
    {
        Function::Builtin {
            name: name.into(),
            func: func,
        }
    }
}

impl fmt::Debug for Function {
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[allow(unused_variables)]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Function::Builtin { ref name, ref func }
                => write!(f, "#[{}]", name),
            &Function::User { ref name, ref params, ref body, }
                => write!(f, "(fn [{}] {})", params.iter().join(" "), body.iter().join("\n")),
        }
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Expr::Nil => write!(f, "()"),
            Expr::Func(ref func) => write!(f, "{}", func),
            Expr::Atom(ref atom) => write!(f, "{}", atom),
            Expr::List(ref list) => write!(f, "{}", list),
            Expr::Vector(ref vec) => write!(f, "{}", vec),
        }
    }
}

impl fmt::Display for Atom {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Atom::Bool(boolean) => write!(f, "#{}", if boolean { "t" } else { "f" }),
            Atom::Int(int) => write!(f, "{}", int),
            Atom::Flt(flt) => write!(f, "{}", flt),
            Atom::Str(ref string) => write!(f, "\"{}\"", string),
            Atom::Sym(ref sym) => write!(f, "#{}", sym.0),
        }
    }
}

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({})", self.0.iter().join(" "))
    }
}

impl fmt::Display for Vector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}]", self.0.iter().join(" "))
    }
}

impl fmt::Display for Function {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }
}

impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<T> From<T> for Expr
where
    T: Into<Atom>,
{
    fn from(x: T) -> Expr {
        Expr::Atom(x.into())
    }
}

impl From<Function> for Expr {
    fn from(x: Function) -> Expr {
        Expr::Func(Arc::new(x))
    }
}

impl<T> From<T> for Atom
where
    T: Into<Literal>,
{
    fn from(x: T) -> Self {
        match x.into() {
            Literal::Bool(y) => Atom::Bool(y),
            Literal::Int(y) => Atom::Int(y),
            Literal::Flt(y) => Atom::Flt(y),
            Literal::Str(y) => Atom::Str(y),
        }
    }
}

impl From<Symbol> for Atom {
    fn from(x: Symbol) -> Self {
        Atom::Sym(x)
    }
}

impl From<Vector> for List {
    fn from(x: Vector) -> Self {
        List(x.0)
    }
}

impl From<List> for Vector {
    fn from(x: List) -> Self {
        Vector(x.0)
    }
}

impl PartialEq for List {
    fn eq(&self, other: &Self) -> bool {
        self.0.len() == other.0.len() && self.0.iter().zip(&other.0).all(|(a, b)| a == b)
    }
}

impl PartialEq for Vector {
    fn eq(&self, other: &Self) -> bool {
        self.0.len() == other.0.len() && self.0.iter().zip(&other.0).all(|(a, b)| a == b)
    }
}

impl PartialEq for Expr {
    fn eq(&self, other: &Self) -> bool {
        use self::Expr::*;
        match (self, other) {
            (&Nil, &Nil) => true,
            (&Func(_), &Func(_)) => false,
            (&Atom(ref a), &Atom(ref b)) => a == b,
            (&List(ref a), &List(ref b)) => a == b,
            (&Vector(ref a), &Vector(ref b)) => a == b,
            _ => false,
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use eval::Env;
    use ops;

    #[test]
    fn call_fn() {
        let mut env = ops::env();
        let add = env.lookup("+").and_then(|f| f.func().cloned()).expect(
            "Expected #[+] in builtins",
        );

        let nums: Vec<Expr> = vec![1i64, 2i64].into_iter().map(Expr::from).collect();
        let result = add.apply(nums.as_slice(), &mut env);
        assert_eq!(Expr::from(3), result.unwrap());
    }

    #[test]
    fn test_env() {
        let new_scope = Env::default();
        assert!(new_scope.lookup("hello").is_none());
    }
}
<commit_msg>Remove '#' from symbol display repr<commit_after>#![allow(dead_code)]

use std::sync::Arc;
use error::*;
use eval::Env;
use itertools::Itertools;
use std::fmt;
use token::Literal;

#[derive(Clone, Debug)]
pub enum Expr {
    Nil,
    Func(Arc<Function>),
    Atom(Atom),
    List(List),
    Vector(Vector),
}

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum Atom {
    Bool(bool),
    Int(i64),
    Flt(f64),
    Str(String),
    Sym(Symbol),
}

#[derive(Clone, Debug)]
pub struct List(pub Vec<Expr>);

#[derive(Clone, Debug)]
pub struct Vector(pub Vec<Expr>);

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Symbol(pub String);

pub enum Function {
    Builtin { name: String, func: Lambda },
    User {
        name: Option<String>,
        params: Vec<Symbol>,
        body: Vec<Expr>,
    },
}

pub type Lambda = fn(&[Expr], &Env) -> Result<Expr>;

impl Expr {
    pub fn atom(&self) -> Option<&Atom> {
        if let &Expr::Atom(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn list(&self) -> Option<&List> {
        if let &Expr::List(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn vector(&self) -> Option<&Vector> {
        if let &Expr::Vector(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn func(&self) -> Option<&Function> {
        if let &Expr::Func(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn sym(&self) -> Option<&Symbol> {
        self.atom().and_then(|a| a.sym())
    }

    pub fn truthiness(&self) -> bool {
        match self {
            &Expr::Nil => false,
            &Expr::Atom(ref a) => {
                match a {
                    &Atom::Bool(b) => b,
                    _ => true,
                }
            }
            _ => true,
        }
    }
}

impl Atom {
    pub fn is_boolean(&self) -> bool {
        self.boolean().is_some()
    }

    pub fn is_int(&self) -> bool {
        self.int().is_some()
    }

    pub fn is_flt(&self) -> bool {
        self.flt().is_some()
    }

    pub fn is_str(&self) -> bool {
        self.str().is_some()
    }

    pub fn is_num(&self) -> bool {
        match self {
            &Atom::Flt(_) | &Atom::Int(_) => true,
            _ => false,
        }
    }

    pub fn boolean(&self) -> Option<bool> {
        if let &Atom::Bool(x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn int(&self) -> Option<i64> {
        if let &Atom::Int(x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn flt(&self) -> Option<f64> {
        if let &Atom::Flt(x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn str(&self) -> Option<&str> {
        if let &Atom::Str(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn sym(&self) -> Option<&Symbol> {
        if let &Atom::Sym(ref x) = self {
            Some(x)
        } else {
            None
        }
    }

    pub fn map_int<A, F>(self, f: F) -> Atom
    where
        F: FnOnce(i64) -> A,
        A: Into<Atom>,
    {
        match self {
            Atom::Int(int) => f(int).into(),
            _ => self,
        }
    }

    pub fn map_flt<A, F>(self, f: F) -> Atom
    where
        F: FnOnce(f64) -> A,
        A: Into<Atom>,
    {
        match self {
            Atom::Flt(flt) => f(flt).into(),
            _ => self,
        }
    }
}

impl Function {
    pub fn builtin<S>(name: S, func: Lambda) -> Self
    where
        S: Into<String>,
    {
        Function::Builtin {
            name: name.into(),
            func: func,
        }
    }
}

impl fmt::Debug for Function {
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[allow(unused_variables)]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Function::Builtin { ref name, ref func }
                => write!(f, "#[{}]", name),
            &Function::User { ref name, ref params, ref body, }
                => write!(f, "(fn [{}] {})", params.iter().join(" "), body.iter().join("\n")),
        }
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Expr::Nil => write!(f, "()"),
            Expr::Func(ref func) => write!(f, "{}", func),
            Expr::Atom(ref atom) => write!(f, "{}", atom),
            Expr::List(ref list) => write!(f, "{}", list),
            Expr::Vector(ref vec) => write!(f, "{}", vec),
        }
    }
}

impl fmt::Display for Atom {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Atom::Bool(boolean) => write!(f, "#{}", if boolean { "t" } else { "f" }),
            Atom::Int(int) => write!(f, "{}", int),
            Atom::Flt(flt) => write!(f, "{}", flt),
            Atom::Str(ref string) => write!(f, "\"{}\"", string),
            Atom::Sym(ref sym) => write!(f, "{}", sym.0),
        }
    }
}

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({})", self.0.iter().join(" "))
    }
}

impl fmt::Display for Vector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}]", self.0.iter().join(" "))
    }
}

impl fmt::Display for Function {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }
}

impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<T> From<T> for Expr
where
    T: Into<Atom>,
{
    fn from(x: T) -> Expr {
        Expr::Atom(x.into())
    }
}

impl From<Function> for Expr {
    fn from(x: Function) -> Expr {
        Expr::Func(Arc::new(x))
    }
}

impl<T> From<T> for Atom
where
    T: Into<Literal>,
{
    fn from(x: T) -> Self {
        match x.into() {
            Literal::Bool(y) => Atom::Bool(y),
            Literal::Int(y) => Atom::Int(y),
            Literal::Flt(y) => Atom::Flt(y),
            Literal::Str(y) => Atom::Str(y),
        }
    }
}

impl From<Symbol> for Atom {
    fn from(x: Symbol) -> Self {
        Atom::Sym(x)
    }
}

impl From<Vector> for List {
    fn from(x: Vector) -> Self {
        List(x.0)
    }
}

impl From<List> for Vector {
    fn from(x: List) -> Self {
        Vector(x.0)
    }
}

impl PartialEq for List {
    fn eq(&self, other: &Self) -> bool {
        self.0.len() == other.0.len() && self.0.iter().zip(&other.0).all(|(a, b)| a == b)
    }
}

impl PartialEq for Vector {
    fn eq(&self, other: &Self) -> bool {
        self.0.len() == other.0.len() && self.0.iter().zip(&other.0).all(|(a, b)| a == b)
    }
}

impl PartialEq for Expr {
    fn eq(&self, other: &Self) -> bool {
        use self::Expr::*;
        match (self, other) {
            (&Nil, &Nil) => true,
            (&Func(_), &Func(_)) => false,
            (&Atom(ref a), &Atom(ref b)) => a == b,
            (&List(ref a), &List(ref b)) => a == b,
            (&Vector(ref a), &Vector(ref b)) => a == b,
            _ => false,
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use eval::Env;
    use ops;

    #[test]
    fn call_fn() {
        let mut env = ops::env();
        let add = env.lookup("+").and_then(|f| f.func().cloned()).expect(
            "Expected #[+] in builtins",
        );

        let nums: Vec<Expr> = vec![1i64, 2i64].into_iter().map(Expr::from).collect();
        let result = add.apply(nums.as_slice(), &mut env);
        assert_eq!(Expr::from(3), result.unwrap());
    }

    #[test]
    fn test_env() {
        let new_scope = Env::default();
        assert!(new_scope.lookup("hello").is_none());
    }
}
<|endoftext|>


<commit_before>//! # gpio module
//!
//! This module provides access to the GPIO of the stm32f0 board.
//! You can:
//!
//! * configure a PIN in Input or Output
//! * read or write the PIN depending on its configuration
//!
//! ## Examples
//!
//! ```
//! extern crate stm32f0_hal;
//!
//! use stm32f0_hal::gpio;
//!
// ! let p_in = gpio::Input::setup(gpio::Pin::PA1);
// ! let b = p_in.read();
// !
// ! let p_out = gpio::Output::setup(gpio::Pin::PA5);
// ! p_out.write(true);
//! ```

use cortex_m;
use stm32f0x2::{GPIOA, GPIOC, RCC};

enum Mode {
    Input = 0b00,
    Output = 0b01,
}

/// GPIO Pin available on PORT A
pub enum Pin {
    PA0,
    PA1,
    PA5,
    PC7,
}

/// Input Mode Pin
pub struct Input {
    pin: Pin,
}

impl Input {
    /// Setup a PIN in Input Mode
    pub fn setup(pin: Pin) -> Input {
        setup_pin(&pin, Mode::Input);
        Input { pin }
    }

    /// Read the state of a PIN
    pub fn read(&self) -> bool {
        unsafe {
            match self.pin {
                Pin::PA0 => (*GPIOA.get()).idr.read().idr0().bit(),
                Pin::PA1 => (*GPIOA.get()).idr.read().idr1().bit(),
                Pin::PA5 => (*GPIOA.get()).idr.read().idr5().bit(),
                Pin::PC7 => (*GPIOC.get()).idr.read().idr7().bit(),
            }
        }
    }
}

/// Output Mode Pin
pub struct Output {
    pin: Pin,
}

impl Output {
    /// Setup a PIN in Output Mode
    pub fn setup(pin: Pin) -> Output {
        setup_pin(&pin, Mode::Output);
        Output { pin }
    }
    /// Set the PIN to high
    pub fn high(&mut self) {
        unsafe {
            match self.pin {
                Pin::PA0 => (*GPIOA.get()).bsrr.write(|w| w.bs0().bit(true)),
                Pin::PA1 => (*GPIOA.get()).bsrr.write(|w| w.bs1().bit(true)),
                Pin::PA5 => (*GPIOA.get()).bsrr.write(|w| w.bs5().bit(true)),
                Pin::PC7 => (*GPIOC.get()).bsrr.write(|w| w.bs7().bit(true)),
            }
        }
    }
    /// Set the PIN to low
    pub fn low(&mut self) {
        unsafe {
            match self.pin {
                Pin::PA0 => (*GPIOA.get()).bsrr.write(|w| w.br0().bit(true)),
                Pin::PA1 => (*GPIOA.get()).bsrr.write(|w| w.br1().bit(true)),
                Pin::PA5 => (*GPIOA.get()).bsrr.write(|w| w.br5().bit(true)),
                Pin::PC7 => (*GPIOC.get()).bsrr.write(|w| w.br7().bit(true)),
            }
        }
    }
}

fn setup_pin(pin: &Pin, mode: Mode) {
    cortex_m::interrupt::free(|cs| {
        let rcc = RCC.borrow(cs);

        let gpioa = GPIOA.borrow(cs);
        let gpioc = GPIOC.borrow(cs);
        rcc.ahbenr.modify(|_, w| w.iopaen().enabled().iopcen().enabled(),
        );
        let mode = mode as u8;

        match *pin {
            Pin::PA0 => gpioa.moder.modify(|_, w| w.moder0().bits(mode)),
            Pin::PA1 => gpioa.moder.modify(|_, w| w.moder1().bits(mode)),
            Pin::PA5 => gpioa.moder.modify(|_, w| w.moder5().bits(mode)),
            Pin::PC7 => gpioc.moder.modify(|_, w| w.moder7().bits(mode)),
        }
    });
}
<commit_msg>Fix rustfmt.<commit_after>//! # gpio module
//!
//! This module provides access to the GPIO of the stm32f0 board.
//! You can:
//!
//! * configure a PIN in Input or Output
//! * read or write the PIN depending on its configuration
//!
//! ## Examples
//!
//! ```
//! extern crate stm32f0_hal;
//!
//! use stm32f0_hal::gpio;
//!
// ! let p_in = gpio::Input::setup(gpio::Pin::PA1);
// ! let b = p_in.read();
// !
// ! let p_out = gpio::Output::setup(gpio::Pin::PA5);
// ! p_out.write(true);
//! ```

use cortex_m;
use stm32f0x2::{GPIOA, GPIOC, RCC};

enum Mode {
    Input = 0b00,
    Output = 0b01,
}

/// GPIO Pin available on PORT A
pub enum Pin {
    PA0,
    PA1,
    PA5,
    PC7,
}

/// Input Mode Pin
pub struct Input {
    pin: Pin,
}

impl Input {
    /// Setup a PIN in Input Mode
    pub fn setup(pin: Pin) -> Input {
        setup_pin(&pin, Mode::Input);
        Input { pin }
    }

    /// Read the state of a PIN
    pub fn read(&self) -> bool {
        unsafe {
            match self.pin {
                Pin::PA0 => (*GPIOA.get()).idr.read().idr0().bit(),
                Pin::PA1 => (*GPIOA.get()).idr.read().idr1().bit(),
                Pin::PA5 => (*GPIOA.get()).idr.read().idr5().bit(),
                Pin::PC7 => (*GPIOC.get()).idr.read().idr7().bit(),
            }
        }
    }
}

/// Output Mode Pin
pub struct Output {
    pin: Pin,
}

impl Output {
    /// Setup a PIN in Output Mode
    pub fn setup(pin: Pin) -> Output {
        setup_pin(&pin, Mode::Output);
        Output { pin }
    }
    /// Set the PIN to high
    pub fn high(&mut self) {
        unsafe {
            match self.pin {
                Pin::PA0 => (*GPIOA.get()).bsrr.write(|w| w.bs0().bit(true)),
                Pin::PA1 => (*GPIOA.get()).bsrr.write(|w| w.bs1().bit(true)),
                Pin::PA5 => (*GPIOA.get()).bsrr.write(|w| w.bs5().bit(true)),
                Pin::PC7 => (*GPIOC.get()).bsrr.write(|w| w.bs7().bit(true)),
            }
        }
    }
    /// Set the PIN to low
    pub fn low(&mut self) {
        unsafe {
            match self.pin {
                Pin::PA0 => (*GPIOA.get()).bsrr.write(|w| w.br0().bit(true)),
                Pin::PA1 => (*GPIOA.get()).bsrr.write(|w| w.br1().bit(true)),
                Pin::PA5 => (*GPIOA.get()).bsrr.write(|w| w.br5().bit(true)),
                Pin::PC7 => (*GPIOC.get()).bsrr.write(|w| w.br7().bit(true)),
            }
        }
    }
}

fn setup_pin(pin: &Pin, mode: Mode) {
    cortex_m::interrupt::free(|cs| {
        let rcc = RCC.borrow(cs);

        let gpioa = GPIOA.borrow(cs);
        let gpioc = GPIOC.borrow(cs);
        rcc.ahbenr.modify(
            |_, w| w.iopaen().enabled().iopcen().enabled(),
        );
        let mode = mode as u8;

        match *pin {
            Pin::PA0 => gpioa.moder.modify(|_, w| w.moder0().bits(mode)),
            Pin::PA1 => gpioa.moder.modify(|_, w| w.moder1().bits(mode)),
            Pin::PA5 => gpioa.moder.modify(|_, w| w.moder5().bits(mode)),
            Pin::PC7 => gpioc.moder.modify(|_, w| w.moder7().bits(mode)),
        }
    });
}
<|endoftext|>