<commit_before>use std::sync::Arc;
use std::sync::Mutex;

use futures::task::Task;
use futures::task::park;

use futures::Async;
use futures::Poll;
use futures::stream::Stream;

enum State {
    Open,
    Closed,
    ControllerDead,
}

struct Shared {
    state: State,
    task: Option<Task>,
}

pub struct LatchController {
    shared: Arc<Mutex<Shared>>,
}

pub struct Latch {
    shared: Arc<Mutex<Shared>>,
}

pub fn latch() -> (LatchController, Latch) {
    let shared = Arc::new(Mutex::new(Shared {
        state: State::Closed,
        task: None,
    }));
    (LatchController { shared: shared.clone() }, Latch { shared: shared })
}

impl LatchController {
    pub fn open(&self) {
        let mut guard = self.shared.lock().expect("lock");
        guard.state = State::Open;
        if let Some(task) = guard.task.take() {
            task.unpark();
        }
    }

    pub fn close(&self) {
        let mut guard = self.shared.lock().expect("lock");
        guard.state = State::Closed;
        // no need to unpark, because nobody is subscribed to close
    }
}

impl Drop for LatchController {
    fn drop(&mut self) {
        let mut guard = self.shared.lock().expect("lock");
        guard.state = State::ControllerDead;
        if let Some(task) = guard.task.take() {
            task.unpark();
        }
    }
}

impl Stream for Latch {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let mut guard = self.shared.lock().expect("lock");
        match guard.state {
            State::Open => Ok(Async::Ready(Some(()))),
            State::ControllerDead => Err(()),
            State::Closed => {
                guard.task = Some(park());
                Ok(Async::NotReady)
            }
        }
    }
}
<commit_msg>Optimize Latch with atomics<commit_after>use std::sync::Arc;
use std::sync::Mutex;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;

use futures::task::Task;
use futures::task::park;

use futures::Async;
use futures::Poll;
use futures::stream::Stream;

enum State {
    Open = 0,
    Closed = 1,
    ControllerDead = 2,
}

const OPEN: usize = State::Open as usize;
const CLOSED: usize = State::Closed as usize;
const CONTROLLER_DEAD: usize = State::ControllerDead as usize;

impl State {
    fn from(value: usize) -> State {
        match value {
            OPEN => State::Open,
            CLOSED => State::Closed,
            CONTROLLER_DEAD => State::ControllerDead,
            _ => unreachable!(),
        }
    }
}

struct Guarded {
    task: Option<Task>,
}

struct Shared {
    state: AtomicUsize,
    guarded: Mutex<Guarded>,
}

pub struct LatchController {
    shared: Arc<Shared>,
}

pub struct Latch {
    shared: Arc<Shared>,
}

pub fn latch() -> (LatchController, Latch) {
    let shared = Arc::new(Shared {
        state: AtomicUsize::new(CLOSED),
        guarded: Mutex::new(Guarded {
            task: None,
        }),
    });
    (LatchController { shared: shared.clone() }, Latch { shared: shared })
}

impl LatchController {
    pub fn open(&self) {
        if self.shared.state.load(Ordering::SeqCst) == OPEN as usize {
            return;
        }

        self.shared.state.store(OPEN, Ordering::SeqCst);

        let mut guard = self.shared.guarded.lock().expect("lock");
        if let Some(task) = guard.task.take() {
            task.unpark();
        }
    }

    pub fn close(&self) {
        if self.shared.state.load(Ordering::SeqCst) == CLOSED as usize {
            return;
        }

        self.shared.state.store(CLOSED, Ordering::SeqCst);

        // no need to unpark, because nobody is subscribed to close
    }
}

impl Drop for LatchController {
    fn drop(&mut self) {
        self.shared.state.store(CONTROLLER_DEAD, Ordering::SeqCst);

        let mut guard = self.shared.guarded.lock().expect("lock");
        if let Some(task) = guard.task.take() {
            task.unpark();
        }
    }
}

impl Stream for Latch {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let state = self.shared.state.load(Ordering::SeqCst);
        let state = State::from(state);

        match state {
            State::Open => Ok(Async::Ready(Some(()))),
            State::ControllerDead => Err(()),
            State::Closed => {
                let mut guard = self.shared.guarded.lock().expect("lock");
                guard.task = Some(park());
                Ok(Async::NotReady)
            }
        }
    }
}
<|endoftext|>


<commit_before>pub struct ChessPosition;

pub struct Queen;

impl ChessPosition {
    pub fn new(rank: i32, file: i32) -> Result<Self, i32> {
        unimplemented!("Construct a ChessPosition struct, given the following rank, file: ({}, {}). If the position is invalid return error that contains wrong rank/file.", rank, file);
    }
}

impl Queen {
    pub fn new(_position: ChessPosition) -> Self {
        unimplemented!("Given the chess position, construct a Queen struct.");
    }

    pub fn can_attack(&self, _other: &Queen) -> bool {
        unimplemented!("Determine if this Queen can attack the other Queen");
    }
}
<commit_msg>queen-attack: Displaying ChessPosition and Queen structs in the unimplemented! message<commit_after>#[derive(Debug)]
pub struct ChessPosition;

#[derive(Debug)]
pub struct Queen;

impl ChessPosition {
    pub fn new(rank: i32, file: i32) -> Result<Self, i32> {
        unimplemented!("Construct a ChessPosition struct, given the following rank, file: ({}, {}). If the position is invalid return error that contains wrong rank/file.", rank, file);
    }
}

impl Queen {
    pub fn new(position: ChessPosition) -> Self {
        unimplemented!(
            "Given the chess position {:?}, construct a Queen struct.",
            position
        );
    }

    pub fn can_attack(&self, other: &Queen) -> bool {
        unimplemented!(
            "Determine if this Queen can attack the other Queen {:?}",
            other
        );
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! `RESTful` API and corresponding utilities.

use std::ops::Deref;
use std::marker::PhantomData;
use std::io;
use std::collections::BTreeMap;
use std::fmt;
use std::str::FromStr;

use iron::IronError;
use iron::prelude::*;
use iron::status;
use iron::headers::Cookie;
use hyper::header::{ContentType, SetCookie};
use cookie::Cookie as CookiePair;
use router::Router;
use params;
use serde_json;
use serde::{Serialize, Serializer};
use serde::de::{self, Visitor, Deserialize, Deserializer};
use failure::Fail;

use crypto::{PublicKey, SecretKey};
use encoding::serialize::{FromHex, FromHexError, ToHex, encode_hex};
use storage;

pub mod public;
pub mod private;
#[cfg(test)]
mod tests;

/// List of possible Api errors.
#[derive(Fail, Debug)]
pub enum ApiError {
    /// Storage error.
    #[fail(display = "Storage error: {}", _0)]
    Storage(
        #[cause]
        storage::Error
    ),

    /// Input/output error.
    #[fail(display = "IO error: {}", _0)]
    Io(
        #[cause]
        ::std::io::Error
    ),

    /// Bad request.
    #[fail(display = "Bad request: {}", _0)]
    BadRequest(String),

    /// Internal error.
    #[fail(display = "Internal server error: {}", _0)]
    InternalError(Box<::std::error::Error + Send + Sync>),

    /// Unauthorized error.
    #[fail(display = "Unauthorized")]
    Unauthorized,
}

impl From<io::Error> for ApiError {
    fn from(e: io::Error) -> ApiError {
        ApiError::Io(e)
    }
}

impl From<storage::Error> for ApiError {
    fn from(e: storage::Error) -> ApiError {
        ApiError::Storage(e)
    }
}

impl From<ApiError> for IronError {
    fn from(e: ApiError) -> IronError {
        let code = match e {
            // Note that `status::Unauthorized` does not fit here, because
            //
            // > A server generating a 401 (Unauthorized) response MUST send a
            // > WWW-Authenticate header field containing at least one challenge.
            //
            // https://tools.ietf.org/html/rfc7235#section-4.1
            ApiError::Unauthorized => status::Forbidden,

            ApiError::BadRequest(..) => status::BadRequest,

            ApiError::Storage(..) |
            ApiError::Io(..) |
            ApiError::InternalError(..) => status::InternalServerError,
        };
        let body = {
            let mut map = BTreeMap::new();
            map.insert("debug", format!("{:?}", e));
            map.insert("description", e.to_string());
            ::serde_json::to_string_pretty(&map).unwrap()
        };
        IronError::new(e.compat(), (code, body))
    }
}

/// `Field` that is serialized/deserialized from/to hex.
#[derive(Clone, Debug)]
struct HexField<T: AsRef<[u8]> + Clone>(pub T);

impl<T> Deref for HexField<T>
where
    T: AsRef<[u8]> + Clone,
{
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> Serialize for HexField<T>
where
    T: AsRef<[u8]> + Clone,
{
    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        ser.serialize_str(&encode_hex(&self.0))
    }
}

struct HexVisitor<T>
where
    T: AsRef<[u8]> + Clone + FromHex<Error = FromHexError>,
{
    _p: PhantomData<T>,
}

impl<'v, T> Visitor<'v> for HexVisitor<T>
where
    T: AsRef<[u8]> + Clone + FromHex<Error = FromHexError>,
{
    type Value = HexField<T>;

    fn expecting(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "expected hex represented string")
    }

    fn visit_str<E>(self, s: &str) -> Result<HexField<T>, E>
    where
        E: de::Error,
    {
        let v = T::from_hex(s).map_err(|_| de::Error::custom("Invalid hex"))?;
        Ok(HexField(v))
    }
}

impl<'de, T> Deserialize<'de> for HexField<T>
where
    T: AsRef<[u8]>
        + FromHex<Error = FromHexError>
        + ToHex
        + Clone,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(HexVisitor { _p: PhantomData })
    }
}

/// `Api` trait defines `RESTful` API.
pub trait Api {
    /// Loads hex value from the cookies.
    fn load_hex_value_from_cookie<'a>(
        &self,
        request: &'a Request,
        key: &str,
    ) -> storage::Result<Vec<u8>> {
        if let Some(&Cookie(ref cookies)) = request.headers.get() {
            for cookie in cookies.iter() {
                if let Ok(c) = CookiePair::parse(cookie.as_str()) {
                    if c.name() == key {
                        if let Ok(value) = FromHex::from_hex(c.value()) {
                            return Ok(value);
                        }
                    }
                }
            }
        }
        Err(storage::Error::new(
            format!("Unable to find value with given key {}", key),
        ))
    }

    /// Loads public and secret key from the cookies.
    fn load_keypair_from_cookies(
        &self,
        request: &Request,
    ) -> Result<(PublicKey, SecretKey), ApiError> {
        let public_key = PublicKey::from_slice(
            self.load_hex_value_from_cookie(request, "public_key")?
                .as_ref(),
        );
        let secret_key = SecretKey::from_slice(
            self.load_hex_value_from_cookie(request, "secret_key")?
                .as_ref(),
        );

        let public_key = public_key.ok_or(ApiError::Unauthorized)?;
        let secret_key = secret_key.ok_or(ApiError::Unauthorized)?;
        Ok((public_key, secret_key))
    }

    //TODO: Remove duplicate code
    /// Returns NotFound and some response with cookies.
    fn not_found_response_with_cookies(
        &self,
        json: &serde_json::Value,
        cookies: Option<Vec<String>>,
    ) -> IronResult<Response> {
        let mut resp = Response::with((
            status::NotFound,
            serde_json::to_string_pretty(json).unwrap(),
        ));
        resp.headers.set(ContentType::json());
        if let Some(cookies) = cookies {
            resp.headers.set(SetCookie(cookies));
        }
        Ok(resp)
    }

    /// Returns OK and some response with cookies.
    fn ok_response_with_cookies(
        &self,
        json: &serde_json::Value,
        cookies: Option<Vec<String>>,
    ) -> IronResult<Response> {
        let mut resp = Response::with((status::Ok, serde_json::to_string_pretty(json).unwrap()));
        resp.headers.set(ContentType::json());
        if let Some(cookies) = cookies {
            resp.headers.set(SetCookie(cookies));
        }
        Ok(resp)
    }

    /// Returns OK and some response.
    fn ok_response(&self, json: &serde_json::Value) -> IronResult<Response> {
        self.ok_response_with_cookies(json, None)
    }
    /// Returns NotFound and some response.
    fn not_found_response(&self, json: &serde_json::Value) -> IronResult<Response> {
        self.not_found_response_with_cookies(json, None)
    }

    /// Used to extend Api.
    fn wire<'b>(&self, router: &'b mut Router);
}

fn url_fragment<T>(request: &Request, name: &str) -> Result<T, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    let params = request.extensions.get::<Router>().unwrap();
    let fragment = params.find(name).ok_or_else(|| {
        ApiError::BadRequest(format!("Required parameter '{}' is missing", name))
    })?;
    let value = T::from_str(fragment).map_err(|e| {
        ApiError::BadRequest(format!("Invalid '{}' parameter: {}", name, e))
    })?;
    Ok(value)
}

fn optional_param<T>(request: &mut Request, name: &str) -> Result<Option<T>, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    let map = request.get_ref::<params::Params>().unwrap();
    let value = match map.find(&[name]) {
        Some(&params::Value::String(ref param)) => {
            let value = T::from_str(param).map_err(|e| {
                ApiError::BadRequest(format!("Invalid '{}' parameter: {}", name, e))
            })?;
            Some(value)
        }
        _ => None,
    };
    Ok(value)
}

fn required_param<T>(request: &mut Request, name: &str) -> Result<T, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    optional_param(request, name)?.ok_or_else(|| {
        ApiError::BadRequest(format!("Required parameter '{}' is missing", name))
    })
}
<commit_msg>Minor, remove unneeded absolute path<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! `RESTful` API and corresponding utilities.

use std::ops::Deref;
use std::marker::PhantomData;
use std::io;
use std::collections::BTreeMap;
use std::fmt;
use std::str::FromStr;

use iron::IronError;
use iron::prelude::*;
use iron::status;
use iron::headers::Cookie;
use hyper::header::{ContentType, SetCookie};
use cookie::Cookie as CookiePair;
use router::Router;
use params;
use serde_json;
use serde::{Serialize, Serializer};
use serde::de::{self, Visitor, Deserialize, Deserializer};
use failure::Fail;

use crypto::{PublicKey, SecretKey};
use encoding::serialize::{FromHex, FromHexError, ToHex, encode_hex};
use storage;

pub mod public;
pub mod private;
#[cfg(test)]
mod tests;

/// List of possible Api errors.
#[derive(Fail, Debug)]
pub enum ApiError {
    /// Storage error.
    #[fail(display = "Storage error: {}", _0)]
    Storage(
        #[cause]
        storage::Error
    ),

    /// Input/output error.
    #[fail(display = "IO error: {}", _0)]
    Io(
        #[cause]
        ::std::io::Error
    ),

    /// Bad request.
    #[fail(display = "Bad request: {}", _0)]
    BadRequest(String),

    /// Internal error.
    #[fail(display = "Internal server error: {}", _0)]
    InternalError(Box<::std::error::Error + Send + Sync>),

    /// Unauthorized error.
    #[fail(display = "Unauthorized")]
    Unauthorized,
}

impl From<io::Error> for ApiError {
    fn from(e: io::Error) -> ApiError {
        ApiError::Io(e)
    }
}

impl From<storage::Error> for ApiError {
    fn from(e: storage::Error) -> ApiError {
        ApiError::Storage(e)
    }
}

impl From<ApiError> for IronError {
    fn from(e: ApiError) -> IronError {
        let code = match e {
            // Note that `status::Unauthorized` does not fit here, because
            //
            // > A server generating a 401 (Unauthorized) response MUST send a
            // > WWW-Authenticate header field containing at least one challenge.
            //
            // https://tools.ietf.org/html/rfc7235#section-4.1
            ApiError::Unauthorized => status::Forbidden,

            ApiError::BadRequest(..) => status::BadRequest,

            ApiError::Storage(..) |
            ApiError::Io(..) |
            ApiError::InternalError(..) => status::InternalServerError,
        };
        let body = {
            let mut map = BTreeMap::new();
            map.insert("debug", format!("{:?}", e));
            map.insert("description", e.to_string());
            serde_json::to_string_pretty(&map).unwrap()
        };
        IronError::new(e.compat(), (code, body))
    }
}

/// `Field` that is serialized/deserialized from/to hex.
#[derive(Clone, Debug)]
struct HexField<T: AsRef<[u8]> + Clone>(pub T);

impl<T> Deref for HexField<T>
where
    T: AsRef<[u8]> + Clone,
{
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> Serialize for HexField<T>
where
    T: AsRef<[u8]> + Clone,
{
    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        ser.serialize_str(&encode_hex(&self.0))
    }
}

struct HexVisitor<T>
where
    T: AsRef<[u8]> + Clone + FromHex<Error = FromHexError>,
{
    _p: PhantomData<T>,
}

impl<'v, T> Visitor<'v> for HexVisitor<T>
where
    T: AsRef<[u8]> + Clone + FromHex<Error = FromHexError>,
{
    type Value = HexField<T>;

    fn expecting(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "expected hex represented string")
    }

    fn visit_str<E>(self, s: &str) -> Result<HexField<T>, E>
    where
        E: de::Error,
    {
        let v = T::from_hex(s).map_err(|_| de::Error::custom("Invalid hex"))?;
        Ok(HexField(v))
    }
}

impl<'de, T> Deserialize<'de> for HexField<T>
where
    T: AsRef<[u8]>
        + FromHex<Error = FromHexError>
        + ToHex
        + Clone,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(HexVisitor { _p: PhantomData })
    }
}

/// `Api` trait defines `RESTful` API.
pub trait Api {
    /// Loads hex value from the cookies.
    fn load_hex_value_from_cookie<'a>(
        &self,
        request: &'a Request,
        key: &str,
    ) -> storage::Result<Vec<u8>> {
        if let Some(&Cookie(ref cookies)) = request.headers.get() {
            for cookie in cookies.iter() {
                if let Ok(c) = CookiePair::parse(cookie.as_str()) {
                    if c.name() == key {
                        if let Ok(value) = FromHex::from_hex(c.value()) {
                            return Ok(value);
                        }
                    }
                }
            }
        }
        Err(storage::Error::new(
            format!("Unable to find value with given key {}", key),
        ))
    }

    /// Loads public and secret key from the cookies.
    fn load_keypair_from_cookies(
        &self,
        request: &Request,
    ) -> Result<(PublicKey, SecretKey), ApiError> {
        let public_key = PublicKey::from_slice(
            self.load_hex_value_from_cookie(request, "public_key")?
                .as_ref(),
        );
        let secret_key = SecretKey::from_slice(
            self.load_hex_value_from_cookie(request, "secret_key")?
                .as_ref(),
        );

        let public_key = public_key.ok_or(ApiError::Unauthorized)?;
        let secret_key = secret_key.ok_or(ApiError::Unauthorized)?;
        Ok((public_key, secret_key))
    }

    //TODO: Remove duplicate code
    /// Returns NotFound and some response with cookies.
    fn not_found_response_with_cookies(
        &self,
        json: &serde_json::Value,
        cookies: Option<Vec<String>>,
    ) -> IronResult<Response> {
        let mut resp = Response::with((
            status::NotFound,
            serde_json::to_string_pretty(json).unwrap(),
        ));
        resp.headers.set(ContentType::json());
        if let Some(cookies) = cookies {
            resp.headers.set(SetCookie(cookies));
        }
        Ok(resp)
    }

    /// Returns OK and some response with cookies.
    fn ok_response_with_cookies(
        &self,
        json: &serde_json::Value,
        cookies: Option<Vec<String>>,
    ) -> IronResult<Response> {
        let mut resp = Response::with((status::Ok, serde_json::to_string_pretty(json).unwrap()));
        resp.headers.set(ContentType::json());
        if let Some(cookies) = cookies {
            resp.headers.set(SetCookie(cookies));
        }
        Ok(resp)
    }

    /// Returns OK and some response.
    fn ok_response(&self, json: &serde_json::Value) -> IronResult<Response> {
        self.ok_response_with_cookies(json, None)
    }
    /// Returns NotFound and some response.
    fn not_found_response(&self, json: &serde_json::Value) -> IronResult<Response> {
        self.not_found_response_with_cookies(json, None)
    }

    /// Used to extend Api.
    fn wire<'b>(&self, router: &'b mut Router);
}

fn url_fragment<T>(request: &Request, name: &str) -> Result<T, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    let params = request.extensions.get::<Router>().unwrap();
    let fragment = params.find(name).ok_or_else(|| {
        ApiError::BadRequest(format!("Required parameter '{}' is missing", name))
    })?;
    let value = T::from_str(fragment).map_err(|e| {
        ApiError::BadRequest(format!("Invalid '{}' parameter: {}", name, e))
    })?;
    Ok(value)
}

fn optional_param<T>(request: &mut Request, name: &str) -> Result<Option<T>, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    let map = request.get_ref::<params::Params>().unwrap();
    let value = match map.find(&[name]) {
        Some(&params::Value::String(ref param)) => {
            let value = T::from_str(param).map_err(|e| {
                ApiError::BadRequest(format!("Invalid '{}' parameter: {}", name, e))
            })?;
            Some(value)
        }
        _ => None,
    };
    Ok(value)
}

fn required_param<T>(request: &mut Request, name: &str) -> Result<T, ApiError>
where
    T: FromStr,
    T::Err: fmt::Display,
{
    optional_param(request, name)?.ok_or_else(|| {
        ApiError::BadRequest(format!("Required parameter '{}' is missing", name))
    })
}
<|endoftext|>


<commit_before>use utils::bigint::M256;
use utils::gas::Gas;
use super::commit::{AccountState, BlockhashState};
use super::errors::{RequireError, MachineError, CommitError, EvalError, PCError};
use super::{Stack, Context, BlockHeader, Patch, PC, Storage, Memory, AccountCommitment};

use self::check::check_opcode;
use self::run::run_opcode;
use self::cost::{gas_refund, gas_stipend, gas_cost, memory_cost, memory_gas};

mod cost;
mod run;
mod check;
mod utils;

/// A VM state without PC.
pub struct State<M, S> {
    pub memory: M,
    pub stack: Stack,

    pub context: Context,
    pub block: BlockHeader,
    pub patch: Patch,

    pub out: Vec<u8>,

    pub memory_cost: Gas,
    pub used_gas: Gas,
    pub refunded_gas: Gas,

    pub account_state: AccountState<S>,
    pub blockhash_state: BlockhashState,
}

impl<M, S> State<M, S> {
    pub fn memory_gas(&self) -> Gas {
        memory_gas(self.memory_cost)
    }

    pub fn available_gas(&self) -> Gas {
        self.context.gas_limit - self.memory_gas() - self.used_gas
    }
}

/// A VM state with PC.
pub struct Machine<M, S> {
    state: State<M, S>,
    pc: PC,
    status: MachineStatus,
}

#[derive(Debug, Clone)]
pub enum MachineStatus {
    Running,
    ExitedOk,
    ExitedErr(MachineError),
    InvokeCall(Context, (M256, M256)),
}

#[derive(Debug, Clone)]
pub enum ControlCheck {
    Jump(M256),
}

#[derive(Debug, Clone)]
pub enum Control {
    Stop,
    Jump(M256),
    InvokeCall(Context, (M256, M256)),
}

impl<M: Memory + Default, S: Storage + Default + Clone> Machine<M, S> {
    pub fn new(context: Context, block: BlockHeader, patch: Patch) -> Self {
        Machine {
            pc: PC::new(context.code.as_slice()),
            status: MachineStatus::Running,
            state: State {
                memory: M::default(),
                stack: Stack::default(),

                context: context,
                block: block,
                patch: patch,

                out: Vec::new(),

                memory_cost: Gas::zero(),
                used_gas: Gas::zero(),
                refunded_gas: Gas::zero(),

                account_state: AccountState::default(),
                blockhash_state: BlockhashState::default(),
            },
        }
    }

    pub fn derive(&self, context: Context) -> Self {
        Machine {
            pc: PC::new(context.code.as_slice()),
            status: MachineStatus::Running,
            state: State {
                memory: M::default(),
                stack: Stack::default(),

                context: context,
                block: self.state.block.clone(),
                patch: self.state.patch.clone(),

                out: Vec::new(),

                memory_cost: Gas::zero(),
                used_gas: Gas::zero(),
                refunded_gas: Gas::zero(),

                account_state: self.state.account_state.clone(),
                blockhash_state: self.state.blockhash_state.clone()
            },
        }
    }

    pub fn commit_account(&mut self, commitment: AccountCommitment<S>) -> Result<(), CommitError> {
        self.state.account_state.commit(commitment)
    }

    pub fn commit_blockhash(&mut self, number: M256, hash: M256) -> Result<(), CommitError> {
        self.state.blockhash_state.commit(number, hash)
    }

    #[allow(unused_variables)]
    pub fn apply_sub(&mut self, sub: Machine<M, S>) {
        unimplemented!()
    }

    pub fn check(&self) -> Result<(), EvalError> {
        let instruction = self.pc.peek()?;
        check_opcode(instruction, &self.state).and_then(|v| {
            match v {
                None => Ok(()),
                Some(ControlCheck::Jump(dest)) => {
                    if dest <= M256::from(usize::max_value()) && self.pc.is_valid(dest.into()) {
                        Ok(())
                    } else {
                        Err(EvalError::Machine(MachineError::PC(PCError::BadJumpDest)))
                    }
                }
            }
        })
    }

    pub fn step(&mut self) -> Result<(), RequireError> {
        if self.pc.is_end() {
            self.status = MachineStatus::ExitedOk;
            return Ok(());
        }

        match self.check() {
            Ok(()) => (),
            Err(EvalError::Machine(error)) => {
                self.status = MachineStatus::ExitedErr(error);
                return Ok(());
            },
            Err(EvalError::Require(error)) => {
                return Err(error);
            },
        };

        let instruction = self.pc.peek().unwrap();
        let memory_cost = memory_cost(instruction, &self.state);
        let gas_cost = gas_cost(instruction, &self.state);
        let gas_stipend = gas_stipend(instruction, &self.state);
        let gas_refund = gas_refund(instruction, &self.state);

        if self.state.context.gas_limit < memory_cost + gas_cost {
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
            return Ok(());
        }

        let instruction = self.pc.read().unwrap();
        let available_gas = self.state.available_gas();
        let result = run_opcode((instruction, self.pc.position()),
                                &mut self.state, gas_stipend, available_gas);

        self.state.used_gas = self.state.used_gas + gas_cost;
        self.state.memory_cost = memory_cost;
        self.state.refunded_gas = self.state.refunded_gas + gas_refund;

        match result {
            None => Ok(()),
            Some(Control::Jump(dest)) => {
                self.pc.jump(dest.into()).unwrap();
                Ok(())
            },
            Some(Control::InvokeCall(context, (from, len))) => {
                self.status = MachineStatus::InvokeCall(context, (from, len));
                Ok(())
            },
            Some(Control::Stop) => {
                self.status = MachineStatus::ExitedOk;
                Ok(())
            },
        }
    }

    pub fn state(&self) -> &State<M, S> {
        &self.state
    }

    pub fn status(&self) -> MachineStatus {
        self.status.clone()
    }
}
<commit_msg>Problem: gas check is incorrect Solution: fix gas check<commit_after>use utils::bigint::M256;
use utils::gas::Gas;
use super::commit::{AccountState, BlockhashState};
use super::errors::{RequireError, MachineError, CommitError, EvalError, PCError};
use super::{Stack, Context, BlockHeader, Patch, PC, Storage, Memory, AccountCommitment};

use self::check::check_opcode;
use self::run::run_opcode;
use self::cost::{gas_refund, gas_stipend, gas_cost, memory_cost, memory_gas};

mod cost;
mod run;
mod check;
mod utils;

/// A VM state without PC.
pub struct State<M, S> {
    pub memory: M,
    pub stack: Stack,

    pub context: Context,
    pub block: BlockHeader,
    pub patch: Patch,

    pub out: Vec<u8>,

    pub memory_cost: Gas,
    pub used_gas: Gas,
    pub refunded_gas: Gas,

    pub account_state: AccountState<S>,
    pub blockhash_state: BlockhashState,
}

impl<M, S> State<M, S> {
    pub fn memory_gas(&self) -> Gas {
        memory_gas(self.memory_cost)
    }

    pub fn available_gas(&self) -> Gas {
        self.context.gas_limit - self.memory_gas() - self.used_gas
    }
}

/// A VM state with PC.
pub struct Machine<M, S> {
    state: State<M, S>,
    pc: PC,
    status: MachineStatus,
}

#[derive(Debug, Clone)]
pub enum MachineStatus {
    Running,
    ExitedOk,
    ExitedErr(MachineError),
    InvokeCall(Context, (M256, M256)),
}

#[derive(Debug, Clone)]
pub enum ControlCheck {
    Jump(M256),
}

#[derive(Debug, Clone)]
pub enum Control {
    Stop,
    Jump(M256),
    InvokeCall(Context, (M256, M256)),
}

impl<M: Memory + Default, S: Storage + Default + Clone> Machine<M, S> {
    pub fn new(context: Context, block: BlockHeader, patch: Patch) -> Self {
        Machine {
            pc: PC::new(context.code.as_slice()),
            status: MachineStatus::Running,
            state: State {
                memory: M::default(),
                stack: Stack::default(),

                context: context,
                block: block,
                patch: patch,

                out: Vec::new(),

                memory_cost: Gas::zero(),
                used_gas: Gas::zero(),
                refunded_gas: Gas::zero(),

                account_state: AccountState::default(),
                blockhash_state: BlockhashState::default(),
            },
        }
    }

    pub fn derive(&self, context: Context) -> Self {
        Machine {
            pc: PC::new(context.code.as_slice()),
            status: MachineStatus::Running,
            state: State {
                memory: M::default(),
                stack: Stack::default(),

                context: context,
                block: self.state.block.clone(),
                patch: self.state.patch.clone(),

                out: Vec::new(),

                memory_cost: Gas::zero(),
                used_gas: Gas::zero(),
                refunded_gas: Gas::zero(),

                account_state: self.state.account_state.clone(),
                blockhash_state: self.state.blockhash_state.clone()
            },
        }
    }

    pub fn commit_account(&mut self, commitment: AccountCommitment<S>) -> Result<(), CommitError> {
        self.state.account_state.commit(commitment)
    }

    pub fn commit_blockhash(&mut self, number: M256, hash: M256) -> Result<(), CommitError> {
        self.state.blockhash_state.commit(number, hash)
    }

    #[allow(unused_variables)]
    pub fn apply_sub(&mut self, sub: Machine<M, S>) {
        unimplemented!()
    }

    pub fn check(&self) -> Result<(), EvalError> {
        let instruction = self.pc.peek()?;
        check_opcode(instruction, &self.state).and_then(|v| {
            match v {
                None => Ok(()),
                Some(ControlCheck::Jump(dest)) => {
                    if dest <= M256::from(usize::max_value()) && self.pc.is_valid(dest.into()) {
                        Ok(())
                    } else {
                        Err(EvalError::Machine(MachineError::PC(PCError::BadJumpDest)))
                    }
                }
            }
        })
    }

    pub fn step(&mut self) -> Result<(), RequireError> {
        if self.pc.is_end() {
            self.status = MachineStatus::ExitedOk;
            return Ok(());
        }

        match self.check() {
            Ok(()) => (),
            Err(EvalError::Machine(error)) => {
                self.status = MachineStatus::ExitedErr(error);
                return Ok(());
            },
            Err(EvalError::Require(error)) => {
                return Err(error);
            },
        };

        let instruction = self.pc.peek().unwrap();
        let memory_cost = memory_cost(instruction, &self.state);
        let memory_gas = memory_gas(memory_cost);
        let gas_cost = gas_cost(instruction, &self.state);
        let gas_stipend = gas_stipend(instruction, &self.state);
        let gas_refund = gas_refund(instruction, &self.state);

        if self.state.context.gas_limit < self.state.used_gas + self.state.memory_gas() + memory_gas + gas_cost {
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
            return Ok(());
        }

        let instruction = self.pc.read().unwrap();
        let available_gas = self.state.available_gas();
        let result = run_opcode((instruction, self.pc.position()),
                                &mut self.state, gas_stipend, available_gas);

        self.state.used_gas = self.state.used_gas + gas_cost;
        self.state.memory_cost = memory_cost;
        self.state.refunded_gas = self.state.refunded_gas + gas_refund;

        match result {
            None => Ok(()),
            Some(Control::Jump(dest)) => {
                self.pc.jump(dest.into()).unwrap();
                Ok(())
            },
            Some(Control::InvokeCall(context, (from, len))) => {
                self.status = MachineStatus::InvokeCall(context, (from, len));
                Ok(())
            },
            Some(Control::Stop) => {
                self.status = MachineStatus::ExitedOk;
                Ok(())
            },
        }
    }

    pub fn state(&self) -> &State<M, S> {
        &self.state
    }

    pub fn status(&self) -> MachineStatus {
        self.status.clone()
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 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.

//! The Rust compiler.
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
      html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(custom_attribute)]
#![feature(fs_read_write)]
#![allow(unused_attributes)]
#![feature(i128_type)]
#![feature(i128)]
#![feature(inclusive_range)]
#![feature(inclusive_range_syntax)]
#![feature(libc)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)]
#![feature(conservative_impl_trait)]
#![feature(optin_builtin_traits)]

use rustc::dep_graph::WorkProduct;
use syntax_pos::symbol::Symbol;

#[macro_use]
extern crate bitflags;
extern crate flate2;
extern crate libc;
#[macro_use] extern crate rustc;
extern crate jobserver;
extern crate num_cpus;
extern crate rustc_mir;
extern crate rustc_allocator;
extern crate rustc_apfloat;
extern crate rustc_back;
extern crate rustc_binaryen;
extern crate rustc_const_math;
extern crate rustc_data_structures;
extern crate rustc_demangle;
extern crate rustc_incremental;
extern crate rustc_llvm as llvm;
extern crate rustc_platform_intrinsics as intrinsics;
extern crate rustc_trans_utils;

#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
extern crate syntax_pos;
extern crate rustc_errors as errors;
extern crate serialize;
#[cfg(windows)]
extern crate cc; // Used to locate MSVC
extern crate tempdir;

use back::bytecode::RLIB_BYTECODE_EXTENSION;

pub use llvm_util::{target_features, print_version, print_passes};

use std::any::Any;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::mpsc;

use rustc::dep_graph::DepGraph;
use rustc::hir::def_id::CrateNum;
use rustc::middle::cstore::MetadataLoader;
use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
use rustc::session::{Session, CompileIncomplete};
use rustc::session::config::{OutputFilenames, OutputType, PrintRequest};
use rustc::ty::{self, TyCtxt};
use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc_mir::monomorphize;
use rustc_trans_utils::trans_crate::TransCrate;

mod diagnostics;

pub(crate) mod back {
    mod archive;
    pub mod bytecode;
    mod command;
    pub(crate) mod linker;
    pub mod link;
    mod lto;
    pub(crate) mod symbol_export;
    pub(crate) use rustc_trans_utils::symbol_names;
    pub mod write;
    mod rpath;
}

mod abi;
mod allocator;
mod asm;
mod attributes;
mod base;
mod builder;
mod cabi_aarch64;
mod cabi_arm;
mod cabi_asmjs;
mod cabi_hexagon;
mod cabi_mips;
mod cabi_mips64;
mod cabi_msp430;
mod cabi_nvptx;
mod cabi_nvptx64;
mod cabi_powerpc;
mod cabi_powerpc64;
mod cabi_s390x;
mod cabi_sparc;
mod cabi_sparc64;
mod cabi_x86;
mod cabi_x86_64;
mod cabi_x86_win64;
mod callee;
mod common;
mod consts;
mod context;
mod debuginfo;
mod declare;
mod glue;
mod intrinsic;
mod llvm_util;
mod metadata;
mod meth;
mod mir;
mod time_graph;
mod trans_item;
mod type_;
mod type_of;
mod value;

pub struct LlvmTransCrate(());

impl !Send for LlvmTransCrate {} // Llvm is on a per-thread basis
impl !Sync for LlvmTransCrate {}

impl LlvmTransCrate {
    pub fn new(sess: &Session) -> Box<TransCrate> {
        llvm_util::init(sess); // Make sure llvm is inited
        box LlvmTransCrate(())
    }
}

impl TransCrate for LlvmTransCrate {
    fn print(&self, req: PrintRequest, sess: &Session) {
        match req {
            PrintRequest::RelocationModels => {
                println!("Available relocation models:");
                for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
                    println!("    {}", name);
                }
                println!("");
            }
            PrintRequest::CodeModels => {
                println!("Available code models:");
                for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
                    println!("    {}", name);
                }
                println!("");
            }
            PrintRequest::TlsModels => {
                println!("Available TLS models:");
                for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
                    println!("    {}", name);
                }
                println!("");
            }
            req => llvm_util::print(req, sess),
        }
    }

    fn target_features(&self, sess: &Session) -> Vec<Symbol> {
        target_features(sess)
    }

    fn metadata_loader(&self) -> Box<MetadataLoader> {
        box metadata::LlvmMetadataLoader
    }

    fn provide(&self, providers: &mut ty::maps::Providers) {
        back::symbol_names::provide(providers);
        back::symbol_export::provide(providers);
        base::provide(providers);
        attributes::provide(providers);
    }

    fn provide_extern(&self, providers: &mut ty::maps::Providers) {
        back::symbol_export::provide_extern(providers);
    }

    fn trans_crate<'a, 'tcx>(
        &self,
        tcx: TyCtxt<'a, 'tcx, 'tcx>,
        rx: mpsc::Receiver<Box<Any + Send>>
    ) -> Box<Any> {
        box base::trans_crate(tcx, rx)
    }

    fn join_trans_and_link(
        &self,
        trans: Box<Any>,
        sess: &Session,
        dep_graph: &DepGraph,
        outputs: &OutputFilenames,
    ) -> Result<(), CompileIncomplete>{
        use rustc::util::common::time;
        let trans = trans.downcast::<::back::write::OngoingCrateTranslation>()
            .expect("Expected LlvmTransCrate's OngoingCrateTranslation, found Box<Any>")
            .join(sess, dep_graph);
        if sess.opts.debugging_opts.incremental_info {
            back::write::dump_incremental_data(&trans);
        }

        time(sess.time_passes(),
             "serialize work products",
             move || rustc_incremental::save_work_products(sess, &dep_graph));

        sess.compile_status()?;

        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
                                                   i == OutputType::Metadata) {
            return Ok(());
        }

        // Run the linker on any artifacts that resulted from the LLVM run.
        // This should produce either a finished executable or library.
        time(sess.time_passes(), "linking", || {
            back::link::link_binary(sess, &trans, outputs, &trans.crate_name.as_str());
        });

        // Now that we won't touch anything in the incremental compilation directory
        // any more, we can finalize it (which involves renaming it)
        rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);

        Ok(())
    }
}

pub struct ModuleTranslation {
    /// The name of the module. When the crate may be saved between
    /// compilations, incremental compilation requires that name be
    /// unique amongst **all** crates.  Therefore, it should contain
    /// something unique to this crate (e.g., a module path) as well
    /// as the crate name and disambiguator.
    name: String,
    llmod_id: String,
    pub source: ModuleSource,
    pub kind: ModuleKind,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ModuleKind {
    Regular,
    Metadata,
    Allocator,
}

impl ModuleTranslation {
    pub fn llvm(&self) -> Option<&ModuleLlvm> {
        match self.source {
            ModuleSource::Translated(ref llvm) => Some(llvm),
            ModuleSource::Preexisting(_) => None,
        }
    }

    pub fn into_compiled_module(self,
                                emit_obj: bool,
                                emit_bc: bool,
                                emit_bc_compressed: bool,
                                outputs: &OutputFilenames) -> CompiledModule {
        let pre_existing = match self.source {
            ModuleSource::Preexisting(_) => true,
            ModuleSource::Translated(_) => false,
        };
        let object = if emit_obj {
            Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
        } else {
            None
        };
        let bytecode = if emit_bc {
            Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)))
        } else {
            None
        };
        let bytecode_compressed = if emit_bc_compressed {
            Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
                    .with_extension(RLIB_BYTECODE_EXTENSION))
        } else {
            None
        };

        CompiledModule {
            llmod_id: self.llmod_id,
            name: self.name.clone(),
            kind: self.kind,
            pre_existing,
            object,
            bytecode,
            bytecode_compressed,
        }
    }
}

#[derive(Debug)]
pub struct CompiledModule {
    pub name: String,
    pub llmod_id: String,
    pub kind: ModuleKind,
    pub pre_existing: bool,
    pub object: Option<PathBuf>,
    pub bytecode: Option<PathBuf>,
    pub bytecode_compressed: Option<PathBuf>,
}

pub enum ModuleSource {
    /// Copy the `.o` files or whatever from the incr. comp. directory.
    Preexisting(WorkProduct),

    /// Rebuild from this LLVM module.
    Translated(ModuleLlvm),
}

#[derive(Debug)]
pub struct ModuleLlvm {
    llcx: llvm::ContextRef,
    pub llmod: llvm::ModuleRef,
    tm: llvm::TargetMachineRef,
}

unsafe impl Send for ModuleLlvm { }
unsafe impl Sync for ModuleLlvm { }

impl Drop for ModuleLlvm {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeModule(self.llmod);
            llvm::LLVMContextDispose(self.llcx);
            llvm::LLVMRustDisposeTargetMachine(self.tm);
        }
    }
}

pub struct CrateTranslation {
    pub crate_name: Symbol,
    pub modules: Vec<CompiledModule>,
    allocator_module: Option<CompiledModule>,
    metadata_module: CompiledModule,
    pub link: rustc::middle::cstore::LinkMeta,
    pub metadata: rustc::middle::cstore::EncodedMetadata,
    windows_subsystem: Option<String>,
    linker_info: back::linker::LinkerInfo,
    crate_info: CrateInfo,
}

// Misc info we load from metadata to persist beyond the tcx
pub struct CrateInfo {
    panic_runtime: Option<CrateNum>,
    compiler_builtins: Option<CrateNum>,
    profiler_runtime: Option<CrateNum>,
    sanitizer_runtime: Option<CrateNum>,
    is_no_builtins: FxHashSet<CrateNum>,
    native_libraries: FxHashMap<CrateNum, Rc<Vec<NativeLibrary>>>,
    crate_name: FxHashMap<CrateNum, String>,
    used_libraries: Rc<Vec<NativeLibrary>>,
    link_args: Rc<Vec<String>>,
    used_crate_source: FxHashMap<CrateNum, Rc<CrateSource>>,
    used_crates_static: Vec<(CrateNum, LibSource)>,
    used_crates_dynamic: Vec<(CrateNum, LibSource)>,
}

#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
<commit_msg>Hide more stuff from rustc_trans<commit_after>// Copyright 2012-2013 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.

//! The Rust compiler.
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
      html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(custom_attribute)]
#![feature(fs_read_write)]
#![allow(unused_attributes)]
#![feature(i128_type)]
#![feature(i128)]
#![feature(inclusive_range)]
#![feature(inclusive_range_syntax)]
#![feature(libc)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)]
#![feature(conservative_impl_trait)]
#![feature(optin_builtin_traits)]

use rustc::dep_graph::WorkProduct;
use syntax_pos::symbol::Symbol;

#[macro_use]
extern crate bitflags;
extern crate flate2;
extern crate libc;
#[macro_use] extern crate rustc;
extern crate jobserver;
extern crate num_cpus;
extern crate rustc_mir;
extern crate rustc_allocator;
extern crate rustc_apfloat;
extern crate rustc_back;
extern crate rustc_binaryen;
extern crate rustc_const_math;
extern crate rustc_data_structures;
extern crate rustc_demangle;
extern crate rustc_incremental;
extern crate rustc_llvm as llvm;
extern crate rustc_platform_intrinsics as intrinsics;
extern crate rustc_trans_utils;

#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
extern crate syntax_pos;
extern crate rustc_errors as errors;
extern crate serialize;
#[cfg(windows)]
extern crate cc; // Used to locate MSVC
extern crate tempdir;

use back::bytecode::RLIB_BYTECODE_EXTENSION;

pub use llvm_util::{target_features, print_version, print_passes};

use std::any::Any;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::mpsc;

use rustc::dep_graph::DepGraph;
use rustc::hir::def_id::CrateNum;
use rustc::middle::cstore::MetadataLoader;
use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
use rustc::session::{Session, CompileIncomplete};
use rustc::session::config::{OutputFilenames, OutputType, PrintRequest};
use rustc::ty::{self, TyCtxt};
use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc_mir::monomorphize;
use rustc_trans_utils::trans_crate::TransCrate;

mod diagnostics;

mod back {
    pub use rustc_trans_utils::symbol_names;
    mod archive;
    pub mod bytecode;
    mod command;
    pub mod linker;
    pub mod link;
    mod lto;
    pub mod symbol_export;
    pub mod write;
    mod rpath;
}

mod abi;
mod allocator;
mod asm;
mod attributes;
mod base;
mod builder;
mod cabi_aarch64;
mod cabi_arm;
mod cabi_asmjs;
mod cabi_hexagon;
mod cabi_mips;
mod cabi_mips64;
mod cabi_msp430;
mod cabi_nvptx;
mod cabi_nvptx64;
mod cabi_powerpc;
mod cabi_powerpc64;
mod cabi_s390x;
mod cabi_sparc;
mod cabi_sparc64;
mod cabi_x86;
mod cabi_x86_64;
mod cabi_x86_win64;
mod callee;
mod common;
mod consts;
mod context;
mod debuginfo;
mod declare;
mod glue;
mod intrinsic;
mod llvm_util;
mod metadata;
mod meth;
mod mir;
mod time_graph;
mod trans_item;
mod type_;
mod type_of;
mod value;

pub struct LlvmTransCrate(());

impl !Send for LlvmTransCrate {} // Llvm is on a per-thread basis
impl !Sync for LlvmTransCrate {}

impl LlvmTransCrate {
    pub fn new(sess: &Session) -> Box<TransCrate> {
        llvm_util::init(sess); // Make sure llvm is inited
        box LlvmTransCrate(())
    }
}

impl TransCrate for LlvmTransCrate {
    fn print(&self, req: PrintRequest, sess: &Session) {
        match req {
            PrintRequest::RelocationModels => {
                println!("Available relocation models:");
                for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
                    println!("    {}", name);
                }
                println!("");
            }
            PrintRequest::CodeModels => {
                println!("Available code models:");
                for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
                    println!("    {}", name);
                }
                println!("");
            }
            PrintRequest::TlsModels => {
                println!("Available TLS models:");
                for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
                    println!("    {}", name);
                }
                println!("");
            }
            req => llvm_util::print(req, sess),
        }
    }

    fn target_features(&self, sess: &Session) -> Vec<Symbol> {
        target_features(sess)
    }

    fn metadata_loader(&self) -> Box<MetadataLoader> {
        box metadata::LlvmMetadataLoader
    }

    fn provide(&self, providers: &mut ty::maps::Providers) {
        back::symbol_names::provide(providers);
        back::symbol_export::provide(providers);
        base::provide(providers);
        attributes::provide(providers);
    }

    fn provide_extern(&self, providers: &mut ty::maps::Providers) {
        back::symbol_export::provide_extern(providers);
    }

    fn trans_crate<'a, 'tcx>(
        &self,
        tcx: TyCtxt<'a, 'tcx, 'tcx>,
        rx: mpsc::Receiver<Box<Any + Send>>
    ) -> Box<Any> {
        box base::trans_crate(tcx, rx)
    }

    fn join_trans_and_link(
        &self,
        trans: Box<Any>,
        sess: &Session,
        dep_graph: &DepGraph,
        outputs: &OutputFilenames,
    ) -> Result<(), CompileIncomplete>{
        use rustc::util::common::time;
        let trans = trans.downcast::<::back::write::OngoingCrateTranslation>()
            .expect("Expected LlvmTransCrate's OngoingCrateTranslation, found Box<Any>")
            .join(sess, dep_graph);
        if sess.opts.debugging_opts.incremental_info {
            back::write::dump_incremental_data(&trans);
        }

        time(sess.time_passes(),
             "serialize work products",
             move || rustc_incremental::save_work_products(sess, &dep_graph));

        sess.compile_status()?;

        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
                                                   i == OutputType::Metadata) {
            return Ok(());
        }

        // Run the linker on any artifacts that resulted from the LLVM run.
        // This should produce either a finished executable or library.
        time(sess.time_passes(), "linking", || {
            back::link::link_binary(sess, &trans, outputs, &trans.crate_name.as_str());
        });

        // Now that we won't touch anything in the incremental compilation directory
        // any more, we can finalize it (which involves renaming it)
        rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);

        Ok(())
    }
}

pub struct ModuleTranslation {
    /// The name of the module. When the crate may be saved between
    /// compilations, incremental compilation requires that name be
    /// unique amongst **all** crates.  Therefore, it should contain
    /// something unique to this crate (e.g., a module path) as well
    /// as the crate name and disambiguator.
    name: String,
    llmod_id: String,
    source: ModuleSource,
    kind: ModuleKind,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ModuleKind {
    Regular,
    Metadata,
    Allocator,
}

impl ModuleTranslation {
    fn llvm(&self) -> Option<&ModuleLlvm> {
        match self.source {
            ModuleSource::Translated(ref llvm) => Some(llvm),
            ModuleSource::Preexisting(_) => None,
        }
    }

    fn into_compiled_module(self,
                                emit_obj: bool,
                                emit_bc: bool,
                                emit_bc_compressed: bool,
                                outputs: &OutputFilenames) -> CompiledModule {
        let pre_existing = match self.source {
            ModuleSource::Preexisting(_) => true,
            ModuleSource::Translated(_) => false,
        };
        let object = if emit_obj {
            Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
        } else {
            None
        };
        let bytecode = if emit_bc {
            Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)))
        } else {
            None
        };
        let bytecode_compressed = if emit_bc_compressed {
            Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
                    .with_extension(RLIB_BYTECODE_EXTENSION))
        } else {
            None
        };

        CompiledModule {
            llmod_id: self.llmod_id,
            name: self.name.clone(),
            kind: self.kind,
            pre_existing,
            object,
            bytecode,
            bytecode_compressed,
        }
    }
}

#[derive(Debug)]
pub struct CompiledModule {
    name: String,
    llmod_id: String,
    kind: ModuleKind,
    pre_existing: bool,
    object: Option<PathBuf>,
    bytecode: Option<PathBuf>,
    bytecode_compressed: Option<PathBuf>,
}

enum ModuleSource {
    /// Copy the `.o` files or whatever from the incr. comp. directory.
    Preexisting(WorkProduct),

    /// Rebuild from this LLVM module.
    Translated(ModuleLlvm),
}

#[derive(Debug)]
pub struct ModuleLlvm {
    llcx: llvm::ContextRef,
    llmod: llvm::ModuleRef,
    tm: llvm::TargetMachineRef,
}

unsafe impl Send for ModuleLlvm { }
unsafe impl Sync for ModuleLlvm { }

impl Drop for ModuleLlvm {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeModule(self.llmod);
            llvm::LLVMContextDispose(self.llcx);
            llvm::LLVMRustDisposeTargetMachine(self.tm);
        }
    }
}

pub struct CrateTranslation {
    crate_name: Symbol,
    modules: Vec<CompiledModule>,
    allocator_module: Option<CompiledModule>,
    metadata_module: CompiledModule,
    link: rustc::middle::cstore::LinkMeta,
    metadata: rustc::middle::cstore::EncodedMetadata,
    windows_subsystem: Option<String>,
    linker_info: back::linker::LinkerInfo,
    crate_info: CrateInfo,
}

// Misc info we load from metadata to persist beyond the tcx
pub struct CrateInfo {
    panic_runtime: Option<CrateNum>,
    compiler_builtins: Option<CrateNum>,
    profiler_runtime: Option<CrateNum>,
    sanitizer_runtime: Option<CrateNum>,
    is_no_builtins: FxHashSet<CrateNum>,
    native_libraries: FxHashMap<CrateNum, Rc<Vec<NativeLibrary>>>,
    crate_name: FxHashMap<CrateNum, String>,
    used_libraries: Rc<Vec<NativeLibrary>>,
    link_args: Rc<Vec<String>>,
    used_crate_source: FxHashMap<CrateNum, Rc<CrateSource>>,
    used_crates_static: Vec<(CrateNum, LibSource)>,
    used_crates_dynamic: Vec<(CrateNum, LibSource)>,
}

#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
<|endoftext|>


<commit_before>use std::iter::AdditiveIterator;
use std::fmt;

use context::{
	Context,
	ValueRef,
		Ignored,
		Constant,
		Dynamic,
		Poison,
};

use ast;
use ast::{
	TopType,
	NumberType,
	BitsType,
	Value,
		NumberValue,
		BitsValue,
};
use resolve;
use entity::Entity;
use eval;

// For now, types have nothing to resolve.
// Eventually, some type parameters will be expressions.
pub type Type = ast::TypeExpr;
fn resolve_type(t: ast::TypeExpr) -> Type { t }

#[deriving(Clone)]
pub enum Item<'s> {
	EntityItem(&'s Entity<'s>),
	ValueItem(Type, ValueRef /*Down*/, ValueRef /*Up*/)
}

impl<'s> Eq for Item<'s> {
	fn eq(&self, other: &Item<'s>) -> bool {
		match (self, other) {
			(&ValueItem(ref ta, ref da, ref ua), &ValueItem(ref tb, ref db, ref ub))
				if ta==tb && da==db && ua==ub => true,
			_ => false
		}
	}
}

impl<'s> fmt::Show for Item<'s> {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f.buf, "{:?}", self)
	}
}

fn common_type(a: Type, b: Type) -> Option<Type>{
	match (a, b) {
		(TopType, x) | (x, TopType) => Some(x),
		(a, b) if a == b => Some(a),
		_ => None
	}
}

#[inline]
fn common_type_all<T:Iterator<Type>>(mut l: T) -> Option<Type> {
	l.fold(Some(TopType), |opt_a, b|{opt_a.and_then(|a| common_type(a, b))})
}

// This would take an iterator if it weren't for mozilla/rust#5121
fn count_ref_types<'a, T: Iterator<&'a ValueRef>>(mut l: T) -> Result<(uint, uint, uint), ValueRef> {
	let mut ignores = 0;
	let mut constants = 0;
	let mut dynamics = 0;
	for i in l {
		match *i {
			Ignored      => ignores   += 1,
			Constant(..) => constants += 1,
			Dynamic(..)  => dynamics  += 1,
			Poison(..)   => return Err((*i).clone()),
		}
	}
	return Ok((ignores, constants, dynamics));
}

fn resolve_value_expr<'s>(ctx: &mut Context, scope: &resolve::Scope, e: &ast::Expr) ->  (Type, ValueRef /*Down*/, ValueRef /*Up*/) {
	match resolve_expr(ctx, scope, e) {
		ValueItem(t, du, uu) => (t, du, uu),
		_ => fail!("Expected a value expression"),
	}
}

pub fn resolve_expr<'s>(ctx: &mut Context, scope: &resolve::Scope<'s>, e: &ast::Expr) -> Item<'s> {
	match *e {
		ast::IgnoreExpr => ValueItem(TopType, Ignored, Ignored),

		ast::VarExpr(ref name) => {
			scope.get(name.as_slice()).expect("Undefined variable")
		}

		ast::DotExpr(~ref lexpr, ref name) => {
			match resolve_expr(ctx, scope, lexpr) {
				EntityItem(ref e) => e.get_property(ctx, name.as_slice()).expect("Undefined property"),
				_ => fail!("dot only works on entities"),
			}
		}

		ast::ValueExpr(ref val) => ValueItem(val.get_type(), Constant(val.clone()), Constant(val.clone())),

		ast::FlipExpr(~ref down, ~ref up) => {
			let (down_type, down_ref, _     ) = resolve_value_expr(ctx, scope, down);
			let (up_type,   _,        up_ref) = resolve_value_expr(ctx, scope, up);

			let common_type = common_type(down_type, up_type).expect("Flip expr sides must be of common type");

			ValueItem(common_type, down_ref, up_ref)
		}

		ast::RangeExpr(~ref min_expr, ~ref max_expr) => {
			let (min_type, min_ref, _) = resolve_value_expr(ctx, scope, min_expr);
			let (max_type, max_ref, _) = resolve_value_expr(ctx, scope, max_expr);

			match (min_type, max_type) {
				(NumberType, NumberType) => (),
				_ => fail!("Range expressions must be numeric")
			}

			fn get_const_default_num(v: &ValueRef, d: f64) -> f64 {
				match *v {
					Constant(NumberValue(n)) => n,
					Ignored => d,
					_ => fail!("Range bounds must be constant")
				}
			}

			let min = get_const_default_num(&min_ref, Float::neg_infinity());
			let max = get_const_default_num(&max_ref, Float::infinity());

			let up = ctx.up_op_cell(0, |cell| eval::RangeCheckOp(cell, min, max));

			//TODO: up is not quite dynamic; specifically should be able to be used in a Choose arm
			ValueItem(NumberType, Poison("Range can only be up-evaluated"), up)
		}

		ast::ChooseExpr(~ref e, ref c) => {
			let (e_type, e_down, e_up) = resolve_value_expr(ctx, scope, e);

			let res = c.iter().map(|&(ref l, ref r)| {
				(resolve_value_expr(ctx, scope, l), resolve_value_expr(ctx, scope, r))
			}).to_owned_vec();

			let l_type = common_type_all(res.iter().map(|&((ref t, _, _), _)| *t))
				.expect("Choose expression left arms not of common type");
			let r_type = common_type_all(res.iter().map(|&(_, (ref t, _, _))| *t))
				.expect("Choose expression right arms not of common type");

			common_type(e_type, l_type)
				.expect("Choose expression left arms and base not of common type");

			let down_pairs = res.iter().map(|&((_, ref l, _), (_, ref r, _))| {
				(ctx.get_const(l), ctx.get_const(r))
			}).to_owned_vec();

			let down = match e_down {
				Ignored => Ignored,
				Poison(e) => Poison(e),
				Constant(ref v) => Constant(eval::eval_choose(v, down_pairs).expect("Choice down not complete")),
				Dynamic(d) => ctx.down_op(eval::ChooseOp(d, down_pairs)),
			};

			let up_pairs = res.iter().map(|&((_, _, ref l), (_, _, ref r))| {
				(ctx.get_const(l), ctx.get_const(r))
			}).to_owned_vec();

			let up = match e_up {
				Ignored => Ignored,
				Poison(e) => Poison(e),
				Constant(ref v) => Constant(eval::eval_choose(v, up_pairs).expect("Choice up not complete")),
				Dynamic(d) => ctx.up_op_cell(d, |cell| eval::ChooseOp(cell,
					// Swap the pair because the value coming in to the op is the right side here
					up_pairs.iter().map(|&(ref a, ref b)| (b.clone(), a.clone())).to_owned_vec()
				)),
			};

			// TODO: ignores, check types for case coverage
			ValueItem(r_type, down, up)
		}

		ast::ConcatExpr(ref v) =>  {
			let res = v.iter().map(|e| resolve_value_expr(ctx, scope, e)).to_owned_vec();

			let len = res.iter().map(|&(ref t, _, _)| {
				match *t {
					BitsType(len) => len,
					_ => fail!("Concatinating values that are not bits")
				}
			}).sum();

			fn concat_const<'a, T: Iterator<&'a ValueRef>> (mut l: T) -> Value {
				BitsValue(l.flat_map(|r| {
					match *r {
						Constant(BitsValue(ref b)) => b.iter().map(|x| *x),
						_ => fail!("Counted wrong"),
					}
				}).collect())
			}

			let down_refs = || res.iter().map(|&(_, ref d, _ )| d);
			let down = match count_ref_types(down_refs()) {
				Err(x) => x,
				Ok((_i, 0, 0 )) => Ignored,
				Ok((0, _c, 0 )) => Constant(concat_const(down_refs())),
				Ok((0, _c, _d)) => {
					let args = down_refs().map(|r| {
						match *r {
							Constant(BitsValue(ref b)) => eval::BitsConst(b.clone()),
							Dynamic(cell) => eval::BitsDyn(cell),
							_ => fail!("Typechecker didn't do its job"),
						}
					}).to_owned_vec();
					ctx.down_op(eval::ConcatOp(args))
				}
				Ok((_i, _c, _d)) => Poison("Some bits are ignored in down evaluation")
			};

			let up_refs = || res.iter().map(|&(_, _, ref u)| u);
			let up = match count_ref_types(up_refs()) {
				Err(x) => x,
				Ok((_i, 0, 0)) => Ignored,
				Ok((0, _c, 0)) => Constant(concat_const(up_refs())),
				// TODO: constant + ignore should be able to be used in constant places like Choose arms
				Ok((_i, _c, _d)) => {
					let cell = ctx.up_cell();
					let mut pos = 0;
					res.iter().map(|&(ref t, _, ref r)| {
						match *t {
							BitsType(l) => {
								match *r {
									Constant(BitsValue(ref b)) => {
										let check = ctx.up_cell();
										ctx.up_op(0, eval::CheckOp(check, BitsValue(b.clone())));
										ctx.up_op(check, eval::SliceOp(cell, pos, l));
									}
									Dynamic(c) => ctx.up_op(c, eval::SliceOp(cell, pos, l)),
									Ignored => (),
									_ => fail!(),
								}
								pos += l;
							}
							_ => fail!(),
						}

					}).to_owned_vec();
					Dynamic(cell)
				}
			};

			ValueItem(BitsType(len), down, up)
		}

		ast::BinExpr(~ref a, op, ~ref b) => {
			let (a_type, a_down, a_up) = resolve_value_expr(ctx, scope, a);
			let (b_type, b_down, b_up) = resolve_value_expr(ctx, scope, b);

			let tp = common_type(a_type, b_type).expect("Incompatible types with binary operator");

			let down = match (a_down, b_down) {
				(Ignored, _) | (_, Ignored) => Ignored,
				(Constant(NumberValue(a)), Constant(NumberValue(b))) => Constant(NumberValue(op.eval(a, b))),
				(Dynamic(a), Constant(NumberValue(b))) => ctx.down_op(eval::BinaryConstOp(a, op, b)),
				(Constant(NumberValue(a)), Dynamic(b)) => ctx.down_op(eval::BinaryConstOp(b, op.swap(), a)),
				(Dynamic(a), Dynamic(b))               => ctx.down_op(eval::BinaryOp(a, op, b)),
				(Constant(..), _) | (_, Constant(..)) => fail!("number constant is not a number?"),
				(Poison(e), _) | (_, Poison(e)) => Poison(e),
			};

			let up = match (a_up, b_up) {
				(Ignored, _) | (_, Ignored) => Ignored,
				(Constant(NumberValue(a)), Constant(NumberValue(b))) =>
					Constant(NumberValue(op.eval(a, b))),
				(Dynamic(a), Constant(NumberValue(b))) =>
					ctx.up_op_cell(a, |cell| eval::BinaryConstOp(cell, op.invert(), b)),
				(Constant(NumberValue(a)), Dynamic(b)) =>
					ctx.up_op_cell(b, |cell| eval::BinaryConstOp(cell, op.swap().invert(), a)),
				(Dynamic(_), Dynamic(_)) =>
					Poison("At least one side of an up-evaluated binary operator must be constant"),
				(Constant(..), _) | (_, Constant(..)) => fail!("number constant is not a number?"),
				(Poison(e), _) | (_, Poison(e)) => Poison(e),
			};

			ValueItem(tp, down, up)
		}
	}
}

#[cfg(test)]
mod test {
	use expr::{ValueItem, resolve_expr};
	use session::Session;
	use context::{
		Context,
		ValueRef,
			Ignored,
			Constant,
	};
	use ast::{
		TypeExpr,
			NumberType,
			SymbolType,
			BitsType,
		NumberValue,
		BitsValue,
		SymbolValue,
	};
	use resolve::Scope;
	use grammar;

	fn check_const_value(s: &str, t: TypeExpr, down: ValueRef, up: ValueRef) {
		let ses = Session::new();
		let mut ctx = Context::new(&ses);
		let scope = Scope::new();
		let e = grammar::valexpr(s).unwrap();
		let r = resolve_expr(&mut ctx, &scope, &e);
		assert_eq!(r, ValueItem(t, down, up));
	}

	#[test]
	fn test_const_number() {
		check_const_value("55", NumberType, Constant(NumberValue(55f64)), Constant(NumberValue(55f64)));
	}

	#[test]
	fn test_const_symbol() {
		check_const_value("#foo", SymbolType, Constant(SymbolValue(~"foo")), Constant(SymbolValue(~"foo")));
	}

	#[test]
	fn test_const_add() {
		check_const_value("2 + 3", NumberType, Constant(NumberValue(5f64)), Constant(NumberValue(5f64)));
	}

	#[test]
	fn test_add_ignore() {
		check_const_value("2 + ignore", NumberType, Ignored, Ignored);
	}

	#[test]
	#[should_fail]
	fn test_add_wrongtype() {
		check_const_value("2 + #test", NumberType, Ignored, Ignored); // TODO: make sure it fails for the right reason
	}

	#[test]
	fn test_const_flip() {
		check_const_value("#l!#r", SymbolType, Constant(SymbolValue(~"l")), Constant(SymbolValue(~"r")));
	}

	#[test]
	fn test_const_choice_expr() {
		check_const_value("(#bar)[#foo=#a, #bar=#b, #baz=#c]", SymbolType, Constant(SymbolValue(~"b")), Constant(SymbolValue(~"b")));
	}

	#[test]
	fn test_const_concat_expr() {
		let b = ~[true, false, true, true, true, false];
		check_const_value("['101, '11, '0]", BitsType(6), Constant(BitsValue(b.clone())), Constant(BitsValue(b.clone())));
	}
}
<commit_msg>rust: to_owned_vec -> collect<commit_after>use std::iter::AdditiveIterator;
use std::fmt;

use context::{
	Context,
	ValueRef,
		Ignored,
		Constant,
		Dynamic,
		Poison,
};

use ast;
use ast::{
	TopType,
	NumberType,
	BitsType,
	Value,
		NumberValue,
		BitsValue,
};
use resolve;
use entity::Entity;
use eval;

// For now, types have nothing to resolve.
// Eventually, some type parameters will be expressions.
pub type Type = ast::TypeExpr;
fn resolve_type(t: ast::TypeExpr) -> Type { t }

#[deriving(Clone)]
pub enum Item<'s> {
	EntityItem(&'s Entity<'s>),
	ValueItem(Type, ValueRef /*Down*/, ValueRef /*Up*/)
}

impl<'s> Eq for Item<'s> {
	fn eq(&self, other: &Item<'s>) -> bool {
		match (self, other) {
			(&ValueItem(ref ta, ref da, ref ua), &ValueItem(ref tb, ref db, ref ub))
				if ta==tb && da==db && ua==ub => true,
			_ => false
		}
	}
}

impl<'s> fmt::Show for Item<'s> {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f.buf, "{:?}", self)
	}
}

fn common_type(a: Type, b: Type) -> Option<Type>{
	match (a, b) {
		(TopType, x) | (x, TopType) => Some(x),
		(a, b) if a == b => Some(a),
		_ => None
	}
}

#[inline]
fn common_type_all<T:Iterator<Type>>(mut l: T) -> Option<Type> {
	l.fold(Some(TopType), |opt_a, b|{opt_a.and_then(|a| common_type(a, b))})
}

// This would take an iterator if it weren't for mozilla/rust#5121
fn count_ref_types<'a, T: Iterator<&'a ValueRef>>(mut l: T) -> Result<(uint, uint, uint), ValueRef> {
	let mut ignores = 0;
	let mut constants = 0;
	let mut dynamics = 0;
	for i in l {
		match *i {
			Ignored      => ignores   += 1,
			Constant(..) => constants += 1,
			Dynamic(..)  => dynamics  += 1,
			Poison(..)   => return Err((*i).clone()),
		}
	}
	return Ok((ignores, constants, dynamics));
}

fn resolve_value_expr<'s>(ctx: &mut Context, scope: &resolve::Scope, e: &ast::Expr) ->  (Type, ValueRef /*Down*/, ValueRef /*Up*/) {
	match resolve_expr(ctx, scope, e) {
		ValueItem(t, du, uu) => (t, du, uu),
		_ => fail!("Expected a value expression"),
	}
}

pub fn resolve_expr<'s>(ctx: &mut Context, scope: &resolve::Scope<'s>, e: &ast::Expr) -> Item<'s> {
	match *e {
		ast::IgnoreExpr => ValueItem(TopType, Ignored, Ignored),

		ast::VarExpr(ref name) => {
			scope.get(name.as_slice()).expect("Undefined variable")
		}

		ast::DotExpr(~ref lexpr, ref name) => {
			match resolve_expr(ctx, scope, lexpr) {
				EntityItem(ref e) => e.get_property(ctx, name.as_slice()).expect("Undefined property"),
				_ => fail!("dot only works on entities"),
			}
		}

		ast::ValueExpr(ref val) => ValueItem(val.get_type(), Constant(val.clone()), Constant(val.clone())),

		ast::FlipExpr(~ref down, ~ref up) => {
			let (down_type, down_ref, _     ) = resolve_value_expr(ctx, scope, down);
			let (up_type,   _,        up_ref) = resolve_value_expr(ctx, scope, up);

			let common_type = common_type(down_type, up_type).expect("Flip expr sides must be of common type");

			ValueItem(common_type, down_ref, up_ref)
		}

		ast::RangeExpr(~ref min_expr, ~ref max_expr) => {
			let (min_type, min_ref, _) = resolve_value_expr(ctx, scope, min_expr);
			let (max_type, max_ref, _) = resolve_value_expr(ctx, scope, max_expr);

			match (min_type, max_type) {
				(NumberType, NumberType) => (),
				_ => fail!("Range expressions must be numeric")
			}

			fn get_const_default_num(v: &ValueRef, d: f64) -> f64 {
				match *v {
					Constant(NumberValue(n)) => n,
					Ignored => d,
					_ => fail!("Range bounds must be constant")
				}
			}

			let min = get_const_default_num(&min_ref, Float::neg_infinity());
			let max = get_const_default_num(&max_ref, Float::infinity());

			let up = ctx.up_op_cell(0, |cell| eval::RangeCheckOp(cell, min, max));

			//TODO: up is not quite dynamic; specifically should be able to be used in a Choose arm
			ValueItem(NumberType, Poison("Range can only be up-evaluated"), up)
		}

		ast::ChooseExpr(~ref e, ref c) => {
			let (e_type, e_down, e_up) = resolve_value_expr(ctx, scope, e);

			let res = c.iter().map(|&(ref l, ref r)| {
				(resolve_value_expr(ctx, scope, l), resolve_value_expr(ctx, scope, r))
			}).collect::<Vec<((Type, ValueRef, ValueRef), (Type, ValueRef, ValueRef))>>();

			let l_type = common_type_all(res.iter().map(|&((ref t, _, _), _)| *t))
				.expect("Choose expression left arms not of common type");
			let r_type = common_type_all(res.iter().map(|&(_, (ref t, _, _))| *t))
				.expect("Choose expression right arms not of common type");

			common_type(e_type, l_type)
				.expect("Choose expression left arms and base not of common type");

			let down_pairs = res.iter().map(|&((_, ref l, _), (_, ref r, _))| {
				(ctx.get_const(l), ctx.get_const(r))
			}).collect::<~[_]>();

			let down = match e_down {
				Ignored => Ignored,
				Poison(e) => Poison(e),
				Constant(ref v) => Constant(eval::eval_choose(v, down_pairs).expect("Choice down not complete")),
				Dynamic(d) => ctx.down_op(eval::ChooseOp(d, down_pairs)),
			};

			let up_pairs = res.iter().map(|&((_, _, ref l), (_, _, ref r))| {
				(ctx.get_const(l), ctx.get_const(r))
			}).collect::<Vec<_>>();

			let up = match e_up {
				Ignored => Ignored,
				Poison(e) => Poison(e),
				Constant(ref v) => Constant(eval::eval_choose(v, up_pairs.as_slice()).expect("Choice up not complete")),
				Dynamic(d) => ctx.up_op_cell(d, |cell| eval::ChooseOp(cell,
					// Swap the pair because the value coming in to the op is the right side here
					up_pairs.iter().map(|&(ref a, ref b)| (b.clone(), a.clone())).collect()
				)),
			};

			// TODO: ignores, check types for case coverage
			ValueItem(r_type, down, up)
		}

		ast::ConcatExpr(ref v) =>  {
			let res = v.iter().map(|e| resolve_value_expr(ctx, scope, e)).collect::<Vec<(Type, ValueRef, ValueRef)>>();

			let len = res.iter().map(|&(ref t, _, _)| {
				match *t {
					BitsType(len) => len,
					_ => fail!("Concatinating values that are not bits")
				}
			}).sum();

			fn concat_const<'a, T: Iterator<&'a ValueRef>> (mut l: T) -> Value {
				BitsValue(l.flat_map(|r| {
					match *r {
						Constant(BitsValue(ref b)) => b.iter().map(|x| *x),
						_ => fail!("Counted wrong"),
					}
				}).collect())
			}

			let down_refs = || res.iter().map(|&(_, ref d, _ )| d);
			let down = match count_ref_types(down_refs()) {
				Err(x) => x,
				Ok((_i, 0, 0 )) => Ignored,
				Ok((0, _c, 0 )) => Constant(concat_const(down_refs())),
				Ok((0, _c, _d)) => {
					let args = down_refs().map(|r| {
						match *r {
							Constant(BitsValue(ref b)) => eval::BitsConst(b.clone()),
							Dynamic(cell) => eval::BitsDyn(cell),
							_ => fail!("Typechecker didn't do its job"),
						}
					}).collect();
					ctx.down_op(eval::ConcatOp(args))
				}
				Ok((_i, _c, _d)) => Poison("Some bits are ignored in down evaluation")
			};

			let up_refs = || res.iter().map(|&(_, _, ref u)| u);
			let up = match count_ref_types(up_refs()) {
				Err(x) => x,
				Ok((_i, 0, 0)) => Ignored,
				Ok((0, _c, 0)) => Constant(concat_const(up_refs())),
				// TODO: constant + ignore should be able to be used in constant places like Choose arms
				Ok((_i, _c, _d)) => {
					let cell = ctx.up_cell();
					let mut pos = 0;
					for &(ref t, _, ref r) in res.iter() {
						match *t {
							BitsType(l) => {
								match *r {
									Constant(BitsValue(ref b)) => {
										let check = ctx.up_cell();
										ctx.up_op(0, eval::CheckOp(check, BitsValue(b.clone())));
										ctx.up_op(check, eval::SliceOp(cell, pos, l));
									}
									Dynamic(c) => ctx.up_op(c, eval::SliceOp(cell, pos, l)),
									Ignored => (),
									_ => fail!(),
								}
								pos += l;
							}
							_ => fail!(),
						}

					}
					Dynamic(cell)
				}
			};

			ValueItem(BitsType(len), down, up)
		}

		ast::BinExpr(~ref a, op, ~ref b) => {
			let (a_type, a_down, a_up) = resolve_value_expr(ctx, scope, a);
			let (b_type, b_down, b_up) = resolve_value_expr(ctx, scope, b);

			let tp = common_type(a_type, b_type).expect("Incompatible types with binary operator");

			let down = match (a_down, b_down) {
				(Ignored, _) | (_, Ignored) => Ignored,
				(Constant(NumberValue(a)), Constant(NumberValue(b))) => Constant(NumberValue(op.eval(a, b))),
				(Dynamic(a), Constant(NumberValue(b))) => ctx.down_op(eval::BinaryConstOp(a, op, b)),
				(Constant(NumberValue(a)), Dynamic(b)) => ctx.down_op(eval::BinaryConstOp(b, op.swap(), a)),
				(Dynamic(a), Dynamic(b))               => ctx.down_op(eval::BinaryOp(a, op, b)),
				(Constant(..), _) | (_, Constant(..)) => fail!("number constant is not a number?"),
				(Poison(e), _) | (_, Poison(e)) => Poison(e),
			};

			let up = match (a_up, b_up) {
				(Ignored, _) | (_, Ignored) => Ignored,
				(Constant(NumberValue(a)), Constant(NumberValue(b))) =>
					Constant(NumberValue(op.eval(a, b))),
				(Dynamic(a), Constant(NumberValue(b))) =>
					ctx.up_op_cell(a, |cell| eval::BinaryConstOp(cell, op.invert(), b)),
				(Constant(NumberValue(a)), Dynamic(b)) =>
					ctx.up_op_cell(b, |cell| eval::BinaryConstOp(cell, op.swap().invert(), a)),
				(Dynamic(_), Dynamic(_)) =>
					Poison("At least one side of an up-evaluated binary operator must be constant"),
				(Constant(..), _) | (_, Constant(..)) => fail!("number constant is not a number?"),
				(Poison(e), _) | (_, Poison(e)) => Poison(e),
			};

			ValueItem(tp, down, up)
		}
	}
}

#[cfg(test)]
mod test {
	use expr::{ValueItem, resolve_expr};
	use session::Session;
	use context::{
		Context,
		ValueRef,
			Ignored,
			Constant,
	};
	use ast::{
		TypeExpr,
			NumberType,
			SymbolType,
			BitsType,
		NumberValue,
		BitsValue,
		SymbolValue,
	};
	use resolve::Scope;
	use grammar;

	fn check_const_value(s: &str, t: TypeExpr, down: ValueRef, up: ValueRef) {
		let ses = Session::new();
		let mut ctx = Context::new(&ses);
		let scope = Scope::new();
		let e = grammar::valexpr(s).unwrap();
		let r = resolve_expr(&mut ctx, &scope, &e);
		assert_eq!(r, ValueItem(t, down, up));
	}

	#[test]
	fn test_const_number() {
		check_const_value("55", NumberType, Constant(NumberValue(55f64)), Constant(NumberValue(55f64)));
	}

	#[test]
	fn test_const_symbol() {
		check_const_value("#foo", SymbolType, Constant(SymbolValue(~"foo")), Constant(SymbolValue(~"foo")));
	}

	#[test]
	fn test_const_add() {
		check_const_value("2 + 3", NumberType, Constant(NumberValue(5f64)), Constant(NumberValue(5f64)));
	}

	#[test]
	fn test_add_ignore() {
		check_const_value("2 + ignore", NumberType, Ignored, Ignored);
	}

	#[test]
	#[should_fail]
	fn test_add_wrongtype() {
		check_const_value("2 + #test", NumberType, Ignored, Ignored); // TODO: make sure it fails for the right reason
	}

	#[test]
	fn test_const_flip() {
		check_const_value("#l!#r", SymbolType, Constant(SymbolValue(~"l")), Constant(SymbolValue(~"r")));
	}

	#[test]
	fn test_const_choice_expr() {
		check_const_value("(#bar)[#foo=#a, #bar=#b, #baz=#c]", SymbolType, Constant(SymbolValue(~"b")), Constant(SymbolValue(~"b")));
	}

	#[test]
	fn test_const_concat_expr() {
		let b = ~[true, false, true, true, true, false];
		check_const_value("['101, '11, '0]", BitsType(6), Constant(BitsValue(b.clone())), Constant(BitsValue(b.clone())));
	}
}
<|endoftext|>


<commit_before><commit_msg>Clean up multiple games test to show actual content of remaining bytes<commit_after><|endoftext|>


<commit_before>use serde::{Deserialize, Serialize};
use serde_json::Result;
use std::path::Path;
use std::process::exit;
use std::{env, fs};

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Measurement {
    command: String,
    mean: f64,
    stddev: f64,
    median: f64,
    user: f64,
    system: f64,
    min: f64,
    max: f64,
    times: Vec<f64>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Measurements {
    results: Vec<Measurement>,
}

fn main() {
    // TODO args lib
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("please provide the results directory");
        exit(1);
    }
    let results_directory = &args[1];

    let path = Path::new(&results_directory);
    let result_files = fs::read_dir(path).unwrap();
    let x: Result<Vec<Measurements>> = result_files
        .into_iter()
        .map(|f| {
            f.unwrap().path()
        })
        .filter(|filename| {
            filename
                .extension()
                .and_then(|ext| ext.to_str())
                .map_or(false, |ext| ext.ends_with("json"))
        })
        .map(|filename| {
            println!("{:?}", filename);
            let contents = fs::read_to_string(filename).unwrap();
            serde_json::from_str::<Measurements>(&contents)
        })
        .collect();

    println!("{:?}", x);
}
<commit_msg>add regression type<commit_after>use serde::{Deserialize, Serialize};
use serde_json::Result;
use std::path::Path;
use std::process::exit;
use std::{env, fs};

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Measurement {
    command: String,
    mean: f64,
    stddev: f64,
    median: f64,
    user: f64,
    system: f64,
    min: f64,
    max: f64,
    times: Vec<f64>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Measurements {
    results: Vec<Measurement>,
}

struct Regression {
    threshold: f64,
    difference: f64,
    base: Measurement,
    latest: Measurement,
}

fn regression(base: &Measurement, latest: &Measurement) -> Option<Regression> {
    let threshold = 1.05; // 5% regression threshold
    let difference = latest.median / base.median;
    if difference > threshold {
        Some(Regression {
            threshold: threshold,
            difference: difference,
            base: base.clone(),
            latest: latest.clone(),
        })
    } else {
        None
    }
}

fn main() {
    // TODO args lib
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("please provide the results directory");
        exit(1);
    }
    let results_directory = &args[1];

    let path = Path::new(&results_directory);
    let result_files = fs::read_dir(path).unwrap();
    let x: Result<Vec<Measurement>> = result_files
        .into_iter()
        .map(|f| f.unwrap().path())
        .filter(|filename| {
            filename
                .extension()
                .and_then(|ext| ext.to_str())
                .map_or(false, |ext| ext.ends_with("json"))
        })
        .map(|filename| {
            println!("{:?}", filename);
            let contents = fs::read_to_string(filename).unwrap();
            let measurements: Result<Measurements> = serde_json::from_str(&contents);
            // the way we're running these, the files will each contain exactly one measurement
            measurements.map(|x| x.results[0].clone())
        })
        .collect();

    // TODO exit(1) when Regression is present
    match x {
        Err(e) => panic!("{}", e),
        Ok(_) => (),
    }

    println!("{:?}", x);
}
<|endoftext|>


<commit_before>fn main() {

    //----------------------------
    //Variable bindings
    //----------------------------
    let x: i32 = 5;
    {
        let y: i32 = 3;
        println!("({},{})",x,y)
    }

    //Invalid, y is out of scope
    //println!("({},{})",x,y)

    let y: i32 = 10;
    print_number(x);

    print_sum(x,y);

    println!("x+1={}",add_one(x));

    //Expressions and Statements

    //Invalid: let x = (let y = 5);
    //TODO: Flesh out

    // Divergence

    //diverges()  Calling this will not return anything, due to ! ret type
    //Similar to how println! doesn't return anything

    //We can assign a divergence to any type
    //let x: i32 = diverges();
    //let x: String = diverges();
    //----------------------------
    // Function Pointers
    //----------------------------

    // We can create variable bindings which point to functions

    // Without type inference:
    let f: fn(i32) -> i32 = add_one;

    // With type inference:
    let f = add_one;

    let six = f(5);

    //----------------------------
    // Primitive Types
    //----------------------------

    //Standard fixed sized types, signed/unsigned
    //Variable sixed type depend on underlying OS

    //Arrays
    let a = [1, 2, 3]; // a: [i32; 3]
    let mut m = [1, 2, 3]; // m: [i32; 3]

    //Initiliasing arrays with the same value
    let a = [0; 20]; // a: [i32; 20]Run

    //Subscript notation to access array values

    let b = a[2];

    //Slicing
    //Slice refers to a view inside an arrays
    //Allow safe access without copying

    let a = [0,1,2,3,4,5,6];
    let complete = &a[..]; //All elements
    let middle = &a[1..4]; //Only elements from index 1 to 4

    //Tuples
    //Ordered list of fixed sized

    let x = (1,"hello");
    let x: (i32, &str) = (1, "Hello");

    //&str should be read as a "string slice"

    //You can assign a tuple into annother if they have the same type and arrity (lenght)

    let mut x = (1,2);
    let y = (2,3);

    x = y;

    let (x,y,z) = (1,2,3);
    //This overwrites the bindings in the previous section

    //Tup[le indexing

    let tuple = (x,y,z);

    println!("{} , {} , {}" , tuple.0, tuple.1 , tuple.2);

//

    println!("Finished!");
}

fn diverges() -> ! {
    panic!("This function never returns!");
}

//fn early_return(x: i32) -> i32 {
    //return x + 1; // Return works

    //let y: i32 = 10; Becomes unreachable
//}

fn print_number(x: i32){
        println!("x is {}",x)
}

fn print_sum(x: i32, y: i32){
        println!("x+y is {}",y+x)
}

fn add_one(x: i32) -> i32 {
    x + 1
}
<commit_msg>Vector exaple<commit_after>fn main() {

    //----------------------------
    //Variable bindings
    //----------------------------
    let x: i32 = 5;
    {
        let y: i32 = 3;
        println!("({},{})",x,y)
    }

    //Invalid, y is out of scope
    //println!("({},{})",x,y)

    let y: i32 = 10;
    print_number(x);

    print_sum(x,y);

    println!("x+1={}",add_one(x));

    //Expressions and Statements

    //Invalid: let x = (let y = 5);
    //TODO: Flesh out

    // Divergence

    //diverges()  Calling this will not return anything, due to ! ret type
    //Similar to how println! doesn't return anything

    //We can assign a divergence to any type
    //let x: i32 = diverges();
    //let x: String = diverges();
    //----------------------------
    // Function Pointers
    //----------------------------

    // We can create variable bindings which point to functions

    // Without type inference:
    let f: fn(i32) -> i32 = add_one;

    // With type inference:
    let f = add_one;

    let six = f(5);

    //----------------------------
    // Primitive Types
    //----------------------------

    //Standard fixed sized types, signed/unsigned
    //Variable sixed type depend on underlying OS

    //Arrays
    let a = [1, 2, 3]; // a: [i32; 3]
    let mut m = [1, 2, 3]; // m: [i32; 3]

    //Initiliasing arrays with the same value
    let a = [0; 20]; // a: [i32; 20]Run

    //Subscript notation to access array values

    let b = a[2];

    //Slicing
    //Slice refers to a view inside an arrays
    //Allow safe access without copying

    let a = [0,1,2,3,4,5,6];
    let complete = &a[..]; //All elements
    let middle = &a[1..4]; //Only elements from index 1 to 4

    //Tuples
    //Ordered list of fixed sized

    let x = (1,"hello");
    let x: (i32, &str) = (1, "Hello");

    //&str should be read as a "string slice"

    //You can assign a tuple into annother if they have the same type and arrity (lenght)

    let mut x = (1,2);
    let y = (2,3);

    x = y;

    let (x,y,z) = (1,2,3);
    //This overwrites the bindings in the previous section

    //Tuple indexing

    let tuple = (x,y,z);

    println!("{} , {} , {}" , tuple.0, tuple.1 , tuple.2);

    //Vectors
    //Growable/Dynamic arrays

    let mut v = vec![1,2,3,4,5];

    //Index with usize type
    let i: usize = 0;
    println!("Hi! {}", v[i]);

    //Add an item
    println!("Old vector, v: {:?}" , v);
    v.push(123);
    println!("New vector, v: {:?}" , v);

//

    println!("Finished!");
}

fn diverges() -> ! {
    panic!("This function never returns!");
}

//fn early_return(x: i32) -> i32 {
    //return x + 1; // Return works

    //let y: i32 = 10; Becomes unreachable
//}

fn print_number(x: i32){
        println!("x is {}",x)
}

fn print_sum(x: i32, y: i32){
        println!("x+y is {}",y+x)
}

fn add_one(x: i32) -> i32 {
    x + 1
}
<|endoftext|>