<commit_before>extern crate stopwatch;
extern crate env_logger;

use std::collections::BTreeMap;
use std::fs::{self, OpenOptions};
use std::io::{BufWriter, Write};
use std::path::Path;

use self::stopwatch::Stopwatch;
use rayon::prelude::*;
use rustfmt;
use toml;

mod codegen;

use cargo;
use ::{Service, ServiceConfig, ServiceDefinition};

pub fn generate_services(services: BTreeMap<String, ServiceConfig>, out_dir: &Path) {
    let _ = env_logger::init(); // This initializes the `env_logger`
    if !out_dir.exists() {
        fs::create_dir(out_dir).expect("Unable to create output directory");
    }

    services.par_iter().for_each(|(name, service_config)| {
        let sw = Stopwatch::start_new();
        let service = {
            let service_definition = ServiceDefinition::load(name, &service_config.protocol_version)
                .expect(&format!("Failed to load service {}. Make sure the botocore submodule has been initialized!", name));
            Service::new(service_config.clone(), service_definition)
        };

        let crate_dir = out_dir.join(&name);
        let crate_name = format!("rusoto_{}", &name.replace('-', "_"));

        println!("Generating crate for {} @ {}...", service.full_name(), service.api_version());

        if !crate_dir.exists() {
            fs::create_dir(&crate_dir).expect(&format!("Unable to create directory at {}", crate_dir.display()));
        }

        let service_dependencies = service.get_dependencies();

        let extern_crates = service_dependencies.iter().map(|(k, _)| {
            if k == "xml-rs" {
                return "extern crate xml;".into();
            }
            let safe_name = k.replace("-", "_");
            let use_macro = k == "serde_derive" || k == "log" || k == "lazy_static";
            if use_macro {
                return format!("#[macro_use]\nextern crate {};", safe_name);
            }
            format!("extern crate {};", safe_name)
        }).collect::<Vec<String>>().join("\n");

        let mut cargo_manifest = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(crate_dir.join("Cargo.toml"))
            .expect("Unable to write Cargo.toml");

        let mut name_for_keyword = name.clone().to_string();
        if name_for_keyword.len() >= 20 {
            name_for_keyword = name_for_keyword[..20].to_string();
        }

        let manifest = cargo::Manifest {
            package: cargo::Metadata {
                authors: Some(vec![
                    "Anthony DiMarco <ocramida@gmail.com>".into(),
                    "Jimmy Cuadra <jimmy@jimmycuadra.com>".into(),
                    "Matthew Mayer <matthewkmayer@gmail.com>".into(),
                    "Nikita Pekin <contact@nikitapek.in>".into()
                ]),
                description: Some(format!("AWS SDK for Rust - {} @ {}", service.full_name(), service.api_version())),
                documentation: Some("https://rusoto.github.io/rusoto/rusoto_core/index.html".into()),
                keywords: Some(vec!["AWS".into(), "Amazon".into(), name_for_keyword]),
                license: Some("MIT".into()),
                name: crate_name.clone(),
                readme: Some("README.md".into()),
                repository: Some("https://github.com/rusoto/rusoto".into()),
                version: service_config.version.clone(),
                homepage: Some("https://www.rusoto.org/".into()),
                ..cargo::Metadata::default()
            },
            dependencies: service_dependencies,
            dev_dependencies: vec![
                ("rusoto_mock".to_owned(), cargo::Dependency::Extended {
                    path: Some("../../../mock".into()),
                    version: Some("0.25.0".into()),
                    optional: None,
                    default_features: None,
                    features: None
                })
            ].into_iter().collect(),
            ..cargo::Manifest::default()
        };

        cargo_manifest.write_all(toml::to_string(&manifest).unwrap().as_bytes()).unwrap();

        let mut readme_file = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(crate_dir.join("README.md"))
            .expect("Unable to write README.md");

        let readme = format!(r#"
# Rusoto {short_name}
Rust SDK for {aws_name}

You may be looking for:

* [An overview of Rusoto][rusoto-overview]
* [AWS services supported by Rusoto][supported-aws-services]
* [API documentation][api-documentation]
* [Getting help with Rusoto][rusoto-help]

## Requirements

Rust stable or beta are required to use Rusoto. Nightly is tested, but not guaranteed to be supported. Older
versions _may_ be supported. The currently supported Rust versions can be found in the Rusoto project
[`travis.yml`](https://github.com/rusoto/rusoto/blob/master/.travis.yml).

On Linux, OpenSSL is required.

## Installation

To use `{crate_name}` in your application, add it as a dependency in your `Cargo.toml`:

```toml
[dependencies]
{crate_name} = "{version}"
```

## Contributing

See [CONTRIBUTING][contributing].

## License

Rusoto is distributed under the terms of the MIT license.

See [LICENSE][license] for details.

[api-documentation]: https://rusoto.github.io/rusoto/rusoto/ "API documentation"
[license]: https://github.com/rusoto/rusoto/blob/master/LICENSE "MIT License"
[contributing]: https://github.com/rusoto/rusoto/blob/master/CONTRIBUTING.md "Contributing Guide"
[rusoto-help]: https://www.rusoto.org/help.html "Getting help with Rusoto"
[rusoto-overview]: https://www.rusoto.org/ "Rusoto overview"
[supported-aws-services]: https://www.rusoto.org/supported-aws-services.html "List of AWS services supported by Rusoto"
        "#,
        short_name = service.service_type_name(),
        aws_name = service.full_name(),
        crate_name = crate_name,
        version = service_config.version
        );

        readme_file.write_all(readme.as_bytes()).unwrap();

        {
            let src_dir = crate_dir.join("src");

            if !src_dir.exists() {
                fs::create_dir(&src_dir).expect(&format!("Unable to create directory at {}", src_dir.display()));
            }

            let lib_file_path = src_dir.join("lib.rs");

            let mut lib_file = OpenOptions::new()
                .write(true)
                .truncate(true)
                .create(true)
                .open(&lib_file_path)
                .expect("Unable to write lib.rs");

            let lib_file_contents = format!(r#"
// =================================================================
//
//                           * WARNING *
//
//                    This file is generated!
//
//  Changes made to this file will be overwritten. If changes are
//  required to the generated code, the service_crategen project
//  must be updated to generate the changes.
//
// =================================================================

//! {service_docs}
//!
//! If you're using the service, you're probably looking for [{client_name}](struct.{client_name}.html) and [{trait_name}](trait.{trait_name}.html).

{extern_crates}

mod generated;
mod custom;

pub use generated::*;
pub use custom::*;
            "#,
            service_docs = service.documentation().unwrap_or(&service.full_name().to_owned()),
            client_name = service.client_type_name(),
            trait_name = service.service_type_name(),
            extern_crates = extern_crates
            );

            lib_file.write_all(lib_file_contents.as_bytes()).unwrap();

            let gen_file_path = src_dir.join("generated.rs");

            let gen_file = OpenOptions::new()
                .create(true)
                .write(true)
                .truncate(true)
                .open(&gen_file_path)
                .expect("Unable to write generated.rs");

            let mut gen_writer = BufWriter::new(gen_file);

            codegen::generate_source(&service, &mut gen_writer).unwrap();

            let custom_dir_path = src_dir.join("custom");

            if !custom_dir_path.exists() {
                fs::create_dir(&custom_dir_path).expect(&format!("Unable to create directory at {}", custom_dir_path.display()));
            }

            let custom_mod_file_path = custom_dir_path.join("mod.rs");

            if !custom_mod_file_path.exists() {
                OpenOptions::new()
                    .write(true)
                    .create_new(true)
                    .open(&custom_mod_file_path)
                    .expect("Unable to write mod.rs");
            }
            debug!("Service generation of {} took {}ms", service.full_name(), sw.elapsed_ms());
        }

        {
            let sw = Stopwatch::start_new();
            let src_dir = crate_dir.join("src");
            let gen_file_path = src_dir.join("generated.rs");

            let _ = rustfmt::run(rustfmt::Input::File(gen_file_path), &rustfmt::config::Config {
                write_mode: rustfmt::config::WriteMode::Overwrite,
                error_on_line_overflow: false,
                ..rustfmt::config::Config::default()
            });
            debug!("Rustfmt of {} took {}ms", service.full_name(), sw.elapsed_ms());
        }

        {
            let sw = Stopwatch::start_new();
            let test_resources_dir = crate_dir.join("test_resources");

            if !test_resources_dir.exists() {
                fs::create_dir(&test_resources_dir).expect(&format!("Unable to create directory at {}", test_resources_dir.display()));
            }

            let generated_test_resources_dir = test_resources_dir.join("generated");

            if !generated_test_resources_dir.exists() {
                fs::create_dir(&generated_test_resources_dir).expect(&format!("Unable to create directory at {}", generated_test_resources_dir.display()));
            }

            let test_valid_resources = codegen::tests::find_valid_responses_for_service(&service);
            if !test_valid_resources.is_empty() {
                let test_valid_resources_dir = generated_test_resources_dir.join("valid");

                if !test_valid_resources_dir.exists() {
                    fs::create_dir(&test_valid_resources_dir).expect(&format!("Unable to create directory at {}", generated_test_resources_dir.display()));
                }

                for resource in test_valid_resources {
                    fs::copy(resource.full_path, test_valid_resources_dir.join(&resource.file_name)).expect("Failed to copy test resource file");
                }
            }

            let test_error_resources = codegen::tests::find_error_responses_for_service(&service);
            if !test_error_resources.is_empty() {
                let test_error_resources_dir = generated_test_resources_dir.join("error");

                if !test_error_resources_dir.exists() {
                    fs::create_dir(&test_error_resources_dir).expect(&format!("Unable to create directory at {}", generated_test_resources_dir.display()));
                }

                for resource in test_error_resources {
                    fs::copy(resource.full_path, test_error_resources_dir.join(&resource.file_name)).expect("Failed to copy test resource file");
                }
            }
            debug!("Service test generation from botocore for {} took {}ms", service.full_name(), sw.elapsed_ms());
        }
    });
}<commit_msg>Notify if we can't initialize the logger.<commit_after>extern crate stopwatch;
extern crate env_logger;

use std::collections::BTreeMap;
use std::fs::{self, OpenOptions};
use std::io::{BufWriter, Write};
use std::path::Path;

use self::stopwatch::Stopwatch;
use rayon::prelude::*;
use rustfmt;
use toml;

mod codegen;

use cargo;
use ::{Service, ServiceConfig, ServiceDefinition};

pub fn generate_services(services: BTreeMap<String, ServiceConfig>, out_dir: &Path) {
    if let Err(e) = env_logger::init() {
        println!("Failed to initialize Logger: {:?}", e);
    }
    if !out_dir.exists() {
        fs::create_dir(out_dir).expect("Unable to create output directory");
    }

    services.par_iter().for_each(|(name, service_config)| {
        let sw = Stopwatch::start_new();
        let service = {
            let service_definition = ServiceDefinition::load(name, &service_config.protocol_version)
                .expect(&format!("Failed to load service {}. Make sure the botocore submodule has been initialized!", name));
            Service::new(service_config.clone(), service_definition)
        };

        let crate_dir = out_dir.join(&name);
        let crate_name = format!("rusoto_{}", &name.replace('-', "_"));

        println!("Generating crate for {} @ {}...", service.full_name(), service.api_version());

        if !crate_dir.exists() {
            fs::create_dir(&crate_dir).expect(&format!("Unable to create directory at {}", crate_dir.display()));
        }

        let service_dependencies = service.get_dependencies();

        let extern_crates = service_dependencies.iter().map(|(k, _)| {
            if k == "xml-rs" {
                return "extern crate xml;".into();
            }
            let safe_name = k.replace("-", "_");
            let use_macro = k == "serde_derive" || k == "log" || k == "lazy_static";
            if use_macro {
                return format!("#[macro_use]\nextern crate {};", safe_name);
            }
            format!("extern crate {};", safe_name)
        }).collect::<Vec<String>>().join("\n");

        let mut cargo_manifest = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(crate_dir.join("Cargo.toml"))
            .expect("Unable to write Cargo.toml");

        let mut name_for_keyword = name.clone().to_string();
        if name_for_keyword.len() >= 20 {
            name_for_keyword = name_for_keyword[..20].to_string();
        }

        let manifest = cargo::Manifest {
            package: cargo::Metadata {
                authors: Some(vec![
                    "Anthony DiMarco <ocramida@gmail.com>".into(),
                    "Jimmy Cuadra <jimmy@jimmycuadra.com>".into(),
                    "Matthew Mayer <matthewkmayer@gmail.com>".into(),
                    "Nikita Pekin <contact@nikitapek.in>".into()
                ]),
                description: Some(format!("AWS SDK for Rust - {} @ {}", service.full_name(), service.api_version())),
                documentation: Some("https://rusoto.github.io/rusoto/rusoto_core/index.html".into()),
                keywords: Some(vec!["AWS".into(), "Amazon".into(), name_for_keyword]),
                license: Some("MIT".into()),
                name: crate_name.clone(),
                readme: Some("README.md".into()),
                repository: Some("https://github.com/rusoto/rusoto".into()),
                version: service_config.version.clone(),
                homepage: Some("https://www.rusoto.org/".into()),
                ..cargo::Metadata::default()
            },
            dependencies: service_dependencies,
            dev_dependencies: vec![
                ("rusoto_mock".to_owned(), cargo::Dependency::Extended {
                    path: Some("../../../mock".into()),
                    version: Some("0.25.0".into()),
                    optional: None,
                    default_features: None,
                    features: None
                })
            ].into_iter().collect(),
            ..cargo::Manifest::default()
        };

        cargo_manifest.write_all(toml::to_string(&manifest).unwrap().as_bytes()).unwrap();

        let mut readme_file = OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(crate_dir.join("README.md"))
            .expect("Unable to write README.md");

        let readme = format!(r#"
# Rusoto {short_name}
Rust SDK for {aws_name}

You may be looking for:

* [An overview of Rusoto][rusoto-overview]
* [AWS services supported by Rusoto][supported-aws-services]
* [API documentation][api-documentation]
* [Getting help with Rusoto][rusoto-help]

## Requirements

Rust stable or beta are required to use Rusoto. Nightly is tested, but not guaranteed to be supported. Older
versions _may_ be supported. The currently supported Rust versions can be found in the Rusoto project
[`travis.yml`](https://github.com/rusoto/rusoto/blob/master/.travis.yml).

On Linux, OpenSSL is required.

## Installation

To use `{crate_name}` in your application, add it as a dependency in your `Cargo.toml`:

```toml
[dependencies]
{crate_name} = "{version}"
```

## Contributing

See [CONTRIBUTING][contributing].

## License

Rusoto is distributed under the terms of the MIT license.

See [LICENSE][license] for details.

[api-documentation]: https://rusoto.github.io/rusoto/rusoto/ "API documentation"
[license]: https://github.com/rusoto/rusoto/blob/master/LICENSE "MIT License"
[contributing]: https://github.com/rusoto/rusoto/blob/master/CONTRIBUTING.md "Contributing Guide"
[rusoto-help]: https://www.rusoto.org/help.html "Getting help with Rusoto"
[rusoto-overview]: https://www.rusoto.org/ "Rusoto overview"
[supported-aws-services]: https://www.rusoto.org/supported-aws-services.html "List of AWS services supported by Rusoto"
        "#,
        short_name = service.service_type_name(),
        aws_name = service.full_name(),
        crate_name = crate_name,
        version = service_config.version
        );

        readme_file.write_all(readme.as_bytes()).unwrap();

        {
            let src_dir = crate_dir.join("src");

            if !src_dir.exists() {
                fs::create_dir(&src_dir).expect(&format!("Unable to create directory at {}", src_dir.display()));
            }

            let lib_file_path = src_dir.join("lib.rs");

            let mut lib_file = OpenOptions::new()
                .write(true)
                .truncate(true)
                .create(true)
                .open(&lib_file_path)
                .expect("Unable to write lib.rs");

            let lib_file_contents = format!(r#"
// =================================================================
//
//                           * WARNING *
//
//                    This file is generated!
//
//  Changes made to this file will be overwritten. If changes are
//  required to the generated code, the service_crategen project
//  must be updated to generate the changes.
//
// =================================================================

//! {service_docs}
//!
//! If you're using the service, you're probably looking for [{client_name}](struct.{client_name}.html) and [{trait_name}](trait.{trait_name}.html).

{extern_crates}

mod generated;
mod custom;

pub use generated::*;
pub use custom::*;
            "#,
            service_docs = service.documentation().unwrap_or(&service.full_name().to_owned()),
            client_name = service.client_type_name(),
            trait_name = service.service_type_name(),
            extern_crates = extern_crates
            );

            lib_file.write_all(lib_file_contents.as_bytes()).unwrap();

            let gen_file_path = src_dir.join("generated.rs");

            let gen_file = OpenOptions::new()
                .create(true)
                .write(true)
                .truncate(true)
                .open(&gen_file_path)
                .expect("Unable to write generated.rs");

            let mut gen_writer = BufWriter::new(gen_file);

            codegen::generate_source(&service, &mut gen_writer).unwrap();

            let custom_dir_path = src_dir.join("custom");

            if !custom_dir_path.exists() {
                fs::create_dir(&custom_dir_path).expect(&format!("Unable to create directory at {}", custom_dir_path.display()));
            }

            let custom_mod_file_path = custom_dir_path.join("mod.rs");

            if !custom_mod_file_path.exists() {
                OpenOptions::new()
                    .write(true)
                    .create_new(true)
                    .open(&custom_mod_file_path)
                    .expect("Unable to write mod.rs");
            }
            debug!("Service generation of {} took {}ms", service.full_name(), sw.elapsed_ms());
        }

        {
            let sw = Stopwatch::start_new();
            let src_dir = crate_dir.join("src");
            let gen_file_path = src_dir.join("generated.rs");

            let _ = rustfmt::run(rustfmt::Input::File(gen_file_path), &rustfmt::config::Config {
                write_mode: rustfmt::config::WriteMode::Overwrite,
                error_on_line_overflow: false,
                ..rustfmt::config::Config::default()
            });
            debug!("Rustfmt of {} took {}ms", service.full_name(), sw.elapsed_ms());
        }

        {
            let sw = Stopwatch::start_new();
            let test_resources_dir = crate_dir.join("test_resources");

            if !test_resources_dir.exists() {
                fs::create_dir(&test_resources_dir).expect(&format!("Unable to create directory at {}", test_resources_dir.display()));
            }

            let generated_test_resources_dir = test_resources_dir.join("generated");

            if !generated_test_resources_dir.exists() {
                fs::create_dir(&generated_test_resources_dir).expect(&format!("Unable to create directory at {}", generated_test_resources_dir.display()));
            }

            let test_valid_resources = codegen::tests::find_valid_responses_for_service(&service);
            if !test_valid_resources.is_empty() {
                let test_valid_resources_dir = generated_test_resources_dir.join("valid");

                if !test_valid_resources_dir.exists() {
                    fs::create_dir(&test_valid_resources_dir).expect(&format!("Unable to create directory at {}", generated_test_resources_dir.display()));
                }

                for resource in test_valid_resources {
                    fs::copy(resource.full_path, test_valid_resources_dir.join(&resource.file_name)).expect("Failed to copy test resource file");
                }
            }

            let test_error_resources = codegen::tests::find_error_responses_for_service(&service);
            if !test_error_resources.is_empty() {
                let test_error_resources_dir = generated_test_resources_dir.join("error");

                if !test_error_resources_dir.exists() {
                    fs::create_dir(&test_error_resources_dir).expect(&format!("Unable to create directory at {}", generated_test_resources_dir.display()));
                }

                for resource in test_error_resources {
                    fs::copy(resource.full_path, test_error_resources_dir.join(&resource.file_name)).expect("Failed to copy test resource file");
                }
            }
            debug!("Service test generation from botocore for {} took {}ms", service.full_name(), sw.elapsed_ms());
        }
    });
}<|endoftext|>


<commit_before><commit_msg>Use the ::default() methods that bindgen provides where sensible<commit_after><|endoftext|>


<commit_before><commit_msg>Rename components to read<commit_after><|endoftext|>


<commit_before>// Copyright 2015 The GFX developers.
//
// 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.

extern crate cgmath;
extern crate genmesh;
#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

use gfx::attrib::Floater;
use gfx::traits::*;

gfx_vertex!( Vertex {
    a_Pos@ pos: [Floater<i8>; 3],
    a_Normal@ normal: [Floater<i8>; 3],
});

impl Vertex {
    fn new(p: [i8; 3], n: [i8; 3]) -> Vertex {
        Vertex {
            pos: Floater::cast3(p),
            normal: Floater::cast3(n),
        }
    }
}

gfx_parameters!( ForwardParams {
    u_Transform@ transform: [[f32; 4]; 4],
    u_NormalTransform@ normal_transform: [[f32; 3]; 3],
    u_Color@ color: [f32; 4],
});

gfx_parameters!( ShadowParams {
    u_Transform@ transform: [[f32; 4]; 4],
});

//----------------------------------------

fn create_cube<R: gfx::Resources, F: gfx::Factory<R>>(factory: &mut F)
               -> (gfx::Mesh<R>, gfx::Slice<R>)
{
    let vertex_data = [
        // top (0, 0, 1)
        Vertex::new([-1, -1,  1], [0, 0, 1]),
        Vertex::new([ 1, -1,  1], [0, 0, 1]),
        Vertex::new([ 1,  1,  1], [0, 0, 1]),
        Vertex::new([-1,  1,  1], [0, 0, 1]),
        // bottom (0, 0, -1)
        Vertex::new([-1,  1, -1], [0, 0, -1]),
        Vertex::new([ 1,  1, -1], [0, 0, -1]),
        Vertex::new([ 1, -1, -1], [0, 0, -1]),
        Vertex::new([-1, -1, -1], [0, 0, -1]),
        // right (1, 0, 0)
        Vertex::new([ 1, -1, -1], [1, 0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0, 0]),
        Vertex::new([ 1,  1,  1], [1, 0, 0]),
        Vertex::new([ 1, -1,  1], [1, 0, 0]),
        // left (-1, 0, 0)
        Vertex::new([-1, -1,  1], [-1, 0, 0]),
        Vertex::new([-1,  1,  1], [-1, 0, 0]),
        Vertex::new([-1,  1, -1], [-1, 0, 0]),
        Vertex::new([-1, -1, -1], [-1, 0, 0]),
        // front (0, 1, 0)
        Vertex::new([ 1,  1, -1], [0, 1, 0]),
        Vertex::new([-1,  1, -1], [0, 1, 0]),
        Vertex::new([-1,  1,  1], [0, 1, 0]),
        Vertex::new([ 1,  1,  1], [0, 1, 0]),
        // back (0, -1, 0)
        Vertex::new([ 1, -1,  1], [0, -1, 0]),
        Vertex::new([-1, -1,  1], [0, -1, 0]),
        Vertex::new([-1, -1, -1], [0, -1, 0]),
        Vertex::new([ 1, -1, -1], [0, -1, 0]),
    ];

    let mesh = factory.create_mesh(&vertex_data);

    let index_data: &[u8] = &[
         0,  1,  2,  2,  3,  0, // top
         4,  5,  6,  6,  7,  4, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 13, 14, 14, 15, 12, // left
        16, 17, 18, 18, 19, 16, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = index_data.to_slice(factory, gfx::PrimitiveType::TriangleList);

    (mesh, slice)
}

fn create_plane<R: gfx::Resources, F: gfx::Factory<R>>(factory: &mut F)
                -> (gfx::Mesh<R>, gfx::Slice<R>)
{
    let vertex_data = [
        Vertex::new([ 5, -5,  0], [0, 0, 1]),
        Vertex::new([ 5,  5,  0], [0, 0, 1]),
        Vertex::new([-5, -5,  0], [0, 0, 1]),
        Vertex::new([-5,  5,  0], [0, 0, 1]),
    ];

    let mesh = factory.create_mesh(&vertex_data);
    let slice = mesh.to_slice(gfx::PrimitiveType::TriangleStrip);

    (mesh, slice)
}

//----------------------------------------

struct Camera {
    mx_view: cgmath::Matrix4<f32>,
    projection: cgmath::PerspectiveFov<f32, cgmath::Deg<f32>>,
}

struct Light {
    mx_to_world: cgmath::Matrix4<f32>,
    projection: cgmath::Perspective<f32>,
    color: gfx::ColorValue,
}

struct Entity<R: gfx::Resources> {
    mx_to_world: cgmath::Matrix4<f32>,
    batch_shadow: gfx::batch::OwnedBatch<ShadowParams<R>>,
    batch_forward: gfx::batch::OwnedBatch<ForwardParams<R>>,
}

struct Scene<R: gfx::Resources> {
    camera: Camera,
    lights: Vec<Light>,
    entities: Vec<Entity<R>>,
}

//----------------------------------------

fn make_entity<R: gfx::Resources>(mesh: &gfx::Mesh<R>, slice: &gfx::Slice<R>,
               prog_fw: &gfx::handle::Program<R>, prog_sh: &gfx::handle::Program<R>,
               transform: cgmath::Matrix4<f32>) -> Entity<R>
{
    use cgmath::FixedArray;
    Entity {
        mx_to_world: transform,
        batch_forward: {
            let data = ForwardParams {
                transform: cgmath::Matrix4::identity().into_fixed(),
                normal_transform: cgmath::Matrix3::identity().into_fixed(),
                color: [1.0, 1.0, 1.0, 1.0],
                _r: std::marker::PhantomData,
            };
            let mut batch = gfx::batch::OwnedBatch::new(
                mesh.clone(), prog_fw.clone(), data).unwrap();
            batch.slice = slice.clone();
            batch.state = batch.state.depth(gfx::state::Comparison::LessEqual, true);
            batch
        },
        batch_shadow: {
            let data = ShadowParams {
                transform: cgmath::Matrix4::identity().into_fixed(),
                _r: std::marker::PhantomData,
            };
            let mut batch = gfx::batch::OwnedBatch::new(
                mesh.clone(), prog_sh.clone(), data).unwrap();
            batch.slice = slice.clone();
            batch.state = batch.state.depth(gfx::state::Comparison::LessEqual, true);
            batch
        },
    }
}

fn create_scene<R: gfx::Resources, F: gfx::Factory<R>>(factory: &mut F)
                -> Scene<R>
{
    let program_forward = factory.link_program(
        include_bytes!("shader/forward_150.glslv"),
        include_bytes!("shader/forward_150.glslf"),
    ).unwrap();
    let program_shadow = factory.link_program(
        include_bytes!("shader/shadow_150.glslv"),
        include_bytes!("shader/shadow_150.glslf"),
    ).unwrap();

    let num = 4i32;
    let mut entities: Vec<Entity<_>> = (0i32..num).map(|i| {
        use cgmath::{EuclideanVector, Rotation3};
        let (mesh, slice) = create_cube(factory);
        let disp = cgmath::Vector3::new(
            ((i&1)*2-1) as f32 * 2.0,
            ((i&2)-1) as f32 * 2.0,
            ((i&4)/2) as f32 + 2.0,
        );
        make_entity(&mesh, &slice,
            &program_forward, &program_shadow,
            cgmath::Decomposed {
                disp: disp.clone(),
                rot: cgmath::Quaternion::from_axis_angle(
                    &disp.normalize(),
                    cgmath::deg((i*180/num) as f32).into(),
                ),
                scale: 1f32,
            }.into(),
        )
    }).collect();
    entities.push({
        let (mesh, slice) = create_plane(factory);
        make_entity(&mesh, &slice,
            &program_forward, &program_shadow,
            cgmath::Matrix4::identity())
    });

    let camera = Camera {
        mx_view: cgmath::Matrix4::look_at(
            &cgmath::Point3::new(3.0f32, -10.0, 6.0),
            &cgmath::Point3::new(0f32, 0.0, 0.0),
            &cgmath::Vector3::unit_z(),
        ),
        projection: cgmath::PerspectiveFov {
            fovy: cgmath::deg(45.0f32),
            aspect: 1.0,
            near: 1.0,
            far: 20.0,
        },
    };

    Scene {
        camera: camera,
        lights: Vec::new(), //TODO
        entities: entities,
    }
}

//----------------------------------------

pub fn main() {
    use cgmath::{FixedArray, Matrix};

    let (mut stream, mut device, mut factory) = gfx_window_glutin::init(
        glutin::WindowBuilder::new()
            .with_title("Multi-threaded shadow rendering example with gfx-rs".to_string())
            .with_dimensions(800, 600)
            .with_gl(glutin::GL_CORE)
            .with_depth_buffer(24)
            .build().unwrap()
    );

    let mut scene = create_scene(&mut factory);

    'main: loop {
        // quit when Esc is pressed.
        for event in stream.out.window.poll_events() {
            use glutin::{Event, VirtualKeyCode};
            match event {
                Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape)) => break 'main,
                Event::Closed => break 'main,
                _ => {},
            }
        }

        stream.clear(gfx::ClearData {
            color: [0.3, 0.3, 0.3, 1.0],
            depth: 1.0,
            stencil: 0,
        });

        let mx_vp = {
            let mut proj = scene.camera.projection;
            proj.aspect = stream.get_aspect_ratio();
            let proj_mx: cgmath::Matrix4<_> = proj.into();
            proj_mx.mul_m(&scene.camera.mx_view)
        };
        for ent in scene.entities.iter_mut() {
            ent.batch_forward.param.transform = mx_vp.mul_m(&ent.mx_to_world).into_fixed();
            ent.batch_forward.param.normal_transform = {
                let m = &ent.mx_to_world;
                [[m.x.x, m.x.y, m.x.z],
                [m.y.x, m.y.y, m.y.z],
                [m.z.x, m.z.y, m.z.z]]
            };
            stream.draw(&ent.batch_forward).unwrap();
        }

        stream.present(&mut device);
    }
}
<commit_msg>Shadow - added lights and shadows initialization<commit_after>// Copyright 2015 The GFX developers.
//
// 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.

extern crate cgmath;
extern crate genmesh;
#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

use gfx::attrib::Floater;
use gfx::traits::*;

gfx_vertex!( Vertex {
    a_Pos@ pos: [Floater<i8>; 3],
    a_Normal@ normal: [Floater<i8>; 3],
});

impl Vertex {
    fn new(p: [i8; 3], n: [i8; 3]) -> Vertex {
        Vertex {
            pos: Floater::cast3(p),
            normal: Floater::cast3(n),
        }
    }
}

gfx_parameters!( ForwardParams {
    u_Transform@ transform: [[f32; 4]; 4],
    u_NormalTransform@ normal_transform: [[f32; 3]; 3],
    u_Color@ color: [f32; 4],
    t_Shadow@ shadow: gfx::shade::TextureParam<R>,
});

gfx_parameters!( ShadowParams {
    u_Transform@ transform: [[f32; 4]; 4],
});

//----------------------------------------

fn create_cube<R: gfx::Resources, F: gfx::Factory<R>>(factory: &mut F)
               -> (gfx::Mesh<R>, gfx::Slice<R>)
{
    let vertex_data = [
        // top (0, 0, 1)
        Vertex::new([-1, -1,  1], [0, 0, 1]),
        Vertex::new([ 1, -1,  1], [0, 0, 1]),
        Vertex::new([ 1,  1,  1], [0, 0, 1]),
        Vertex::new([-1,  1,  1], [0, 0, 1]),
        // bottom (0, 0, -1)
        Vertex::new([-1,  1, -1], [0, 0, -1]),
        Vertex::new([ 1,  1, -1], [0, 0, -1]),
        Vertex::new([ 1, -1, -1], [0, 0, -1]),
        Vertex::new([-1, -1, -1], [0, 0, -1]),
        // right (1, 0, 0)
        Vertex::new([ 1, -1, -1], [1, 0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0, 0]),
        Vertex::new([ 1,  1,  1], [1, 0, 0]),
        Vertex::new([ 1, -1,  1], [1, 0, 0]),
        // left (-1, 0, 0)
        Vertex::new([-1, -1,  1], [-1, 0, 0]),
        Vertex::new([-1,  1,  1], [-1, 0, 0]),
        Vertex::new([-1,  1, -1], [-1, 0, 0]),
        Vertex::new([-1, -1, -1], [-1, 0, 0]),
        // front (0, 1, 0)
        Vertex::new([ 1,  1, -1], [0, 1, 0]),
        Vertex::new([-1,  1, -1], [0, 1, 0]),
        Vertex::new([-1,  1,  1], [0, 1, 0]),
        Vertex::new([ 1,  1,  1], [0, 1, 0]),
        // back (0, -1, 0)
        Vertex::new([ 1, -1,  1], [0, -1, 0]),
        Vertex::new([-1, -1,  1], [0, -1, 0]),
        Vertex::new([-1, -1, -1], [0, -1, 0]),
        Vertex::new([ 1, -1, -1], [0, -1, 0]),
    ];

    let mesh = factory.create_mesh(&vertex_data);

    let index_data: &[u8] = &[
         0,  1,  2,  2,  3,  0, // top
         4,  5,  6,  6,  7,  4, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 13, 14, 14, 15, 12, // left
        16, 17, 18, 18, 19, 16, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = index_data.to_slice(factory, gfx::PrimitiveType::TriangleList);

    (mesh, slice)
}

fn create_plane<R: gfx::Resources, F: gfx::Factory<R>>(factory: &mut F)
                -> (gfx::Mesh<R>, gfx::Slice<R>)
{
    let vertex_data = [
        Vertex::new([ 5, -5,  0], [0, 0, 1]),
        Vertex::new([ 5,  5,  0], [0, 0, 1]),
        Vertex::new([-5, -5,  0], [0, 0, 1]),
        Vertex::new([-5,  5,  0], [0, 0, 1]),
    ];

    let mesh = factory.create_mesh(&vertex_data);
    let slice = mesh.to_slice(gfx::PrimitiveType::TriangleStrip);

    (mesh, slice)
}

//----------------------------------------

struct Camera {
    mx_view: cgmath::Matrix4<f32>,
    projection: cgmath::PerspectiveFov<f32, cgmath::Deg<f32>>,
}

struct Light<S> {
    position: cgmath::Point3<f32>,
    mx_view: cgmath::Matrix4<f32>,
    projection: cgmath::Perspective<f32>,
    color: gfx::ColorValue,
    stream: S,
}

struct Entity<R: gfx::Resources> {
    mx_to_world: cgmath::Matrix4<f32>,
    batch_shadow: gfx::batch::OwnedBatch<ShadowParams<R>>,
    batch_forward: gfx::batch::OwnedBatch<ForwardParams<R>>,
}

struct Scene<R: gfx::Resources, S> {
    camera: Camera,
    lights: Vec<Light<S>>,
    entities: Vec<Entity<R>>,
}

//----------------------------------------

fn make_entity<R: gfx::Resources>(mesh: &gfx::Mesh<R>, slice: &gfx::Slice<R>,
               prog_fw: &gfx::handle::Program<R>, prog_sh: &gfx::handle::Program<R>,
               shadow: &gfx::shade::TextureParam<R>, transform: cgmath::Matrix4<f32>)
               -> Entity<R>
{
    use cgmath::FixedArray;
    Entity {
        mx_to_world: transform,
        batch_forward: {
            let data = ForwardParams {
                transform: cgmath::Matrix4::identity().into_fixed(),
                normal_transform: cgmath::Matrix3::identity().into_fixed(),
                color: [1.0, 1.0, 1.0, 1.0],
                shadow: shadow.clone(),
                _r: std::marker::PhantomData,
            };
            let mut batch = gfx::batch::OwnedBatch::new(
                mesh.clone(), prog_fw.clone(), data).unwrap();
            batch.slice = slice.clone();
            batch.state = batch.state.depth(gfx::state::Comparison::LessEqual, true);
            batch
        },
        batch_shadow: {
            let data = ShadowParams {
                transform: cgmath::Matrix4::identity().into_fixed(),
                _r: std::marker::PhantomData,
            };
            let mut batch = gfx::batch::OwnedBatch::new(
                mesh.clone(), prog_sh.clone(), data).unwrap();
            batch.slice = slice.clone();
            batch.state = batch.state.depth(gfx::state::Comparison::LessEqual, true);
            batch
        },
    }
}

fn create_scene<D, F>(_: &D, factory: &mut F)
                -> Scene<D::Resources, gfx::OwnedStream<D, gfx::Plane<D::Resources>>> where
    D: gfx::Device,
    F: gfx::Factory<D::Resources> + gfx::traits::StreamFactory<D>,
{
    let program_forward = factory.link_program(
        include_bytes!("shader/forward_150.glslv"),
        include_bytes!("shader/forward_150.glslf"),
    ).unwrap();
    let program_shadow = factory.link_program(
        include_bytes!("shader/shadow_150.glslv"),
        include_bytes!("shader/shadow_150.glslf"),
    ).unwrap();

    let shadow_array = factory.create_texture(gfx::tex::TextureInfo {
        width: 512,
        height: 512,
        depth: 5,
        levels: 1,
        kind: gfx::tex::TextureKind::Texture2DArray,
        format: gfx::tex::Format::DEPTH24,
    }).unwrap();

    let shadow_param = {
        let mut sinfo = gfx::tex::SamplerInfo::new(
            gfx::tex::FilterMethod::Bilinear,
            gfx::tex::WrapMode::Clamp
        );
        sinfo.comparison = gfx::tex::ComparisonMode::CompareRefToTexture(
            gfx::state::Comparison::Less
        );
        let sampler = factory.create_sampler(sinfo);
        (shadow_array.clone(), Some(sampler))
    };

    let (near, far) = (1f32, 20f32);

    struct EntityDesc {
        offset: cgmath::Vector3<f32>,
        angle: f32,
        scale: f32,
    }

    let cube_descs = vec![
        EntityDesc {
            offset: cgmath::vec3(-2.0, -2.0, 2.0),
            angle: 10.0,
            scale: 0.6,
        },
        EntityDesc {
            offset: cgmath::vec3(2.0, -2.0, 2.0),
            angle: 50.0,
            scale: 1.6,
        },
        EntityDesc {
            offset: cgmath::vec3(-2.0, 2.0, 2.0),
            angle: 140.0,
            scale: 1.1,
        },
        EntityDesc {
            offset: cgmath::vec3(2.0, 2.0, 2.0),
            angle: 210.0,
            scale: 0.9,
        },
    ];

    let mut entities: Vec<Entity<_>> = cube_descs.iter().map(|desc| {
        use cgmath::{EuclideanVector, Rotation3};
        let (mesh, slice) = create_cube(factory);
        make_entity(&mesh, &slice,
            &program_forward, &program_shadow, &shadow_param,
            cgmath::Decomposed {
                disp: desc.offset.clone(),
                rot: cgmath::Quaternion::from_axis_angle(
                    &desc.offset.normalize(),
                    cgmath::deg(desc.angle).into(),
                ),
                scale: desc.scale,
            }.into(),
        )
    }).collect();
    entities.push({
        let (mesh, slice) = create_plane(factory);
        make_entity(&mesh, &slice,
            &program_forward, &program_shadow, &shadow_param,
            cgmath::Matrix4::identity())
    });

    let camera = Camera {
        mx_view: cgmath::Matrix4::look_at(
            &cgmath::Point3::new(3.0f32, -10.0, 6.0),
            &cgmath::Point3::new(0f32, 0.0, 0.0),
            &cgmath::Vector3::unit_z(),
        ),
        projection: cgmath::PerspectiveFov {
            fovy: cgmath::deg(45.0f32),
            aspect: 1.0,
            near: near,
            far: far,
        },
    };

    struct LightDesc {
        pos: cgmath::Point3<f32>,
        color: gfx::ColorValue,
        fov: f32,
    }

    let light_descs = vec![
        LightDesc {
            pos: cgmath::Point3::new(-3.0, 10.0, 3.0),
            color: [1.0, 1.0, 1.0, 1.0],
            fov: 60.0,
        }
    ];

    let lights = light_descs.iter().enumerate().map(|(i, desc)| Light {
        position: desc.pos.clone(),
        mx_view: cgmath::Matrix4::look_at(
            &desc.pos,
            &cgmath::Point3::new(0.0, 0.0, 0.0),
            &cgmath::Vector3::unit_z(),
        ),
        projection: cgmath::PerspectiveFov {
            fovy: cgmath::deg(desc.fov),
            aspect: 1.0,
            near: near,
            far: far,
        }.to_perspective(),
        color: desc.color.clone(),
        stream: factory.create_stream(
            gfx::Plane::Texture(
                shadow_array.clone(),
                0,
                Some(i as gfx::Layer)
            ),
        ),
    }).collect();

    Scene {
        camera: camera,
        lights: lights,
        entities: entities,
    }
}

//----------------------------------------

pub fn main() {
    use cgmath::{FixedArray, Matrix};

    let (mut stream, mut device, mut factory) = gfx_window_glutin::init(
        glutin::WindowBuilder::new()
            .with_title("Multi-threaded shadow rendering example with gfx-rs".to_string())
            .with_dimensions(800, 600)
            .with_gl(glutin::GL_CORE)
            .with_depth_buffer(24)
            .build().unwrap()
    );

    let mut scene = create_scene(&device, &mut factory);

    'main: loop {
        // quit when Esc is pressed.
        for event in stream.out.window.poll_events() {
            use glutin::{Event, VirtualKeyCode};
            match event {
                Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape)) => break 'main,
                Event::Closed => break 'main,
                _ => {},
            }
        }

        stream.clear(gfx::ClearData {
            color: [0.3, 0.3, 0.3, 1.0],
            depth: 1.0,
            stencil: 0,
        });

        let mx_vp = {
            let mut proj = scene.camera.projection;
            proj.aspect = stream.get_aspect_ratio();
            let proj_mx: cgmath::Matrix4<_> = proj.into();
            proj_mx.mul_m(&scene.camera.mx_view)
        };
        for ent in scene.entities.iter_mut() {
            ent.batch_forward.param.transform = mx_vp.mul_m(&ent.mx_to_world).into_fixed();
            ent.batch_forward.param.normal_transform = {
                let m = &ent.mx_to_world;
                [[m.x.x, m.x.y, m.x.z],
                [m.y.x, m.y.y, m.y.z],
                [m.z.x, m.z.y, m.z.z]]
            };
            stream.draw(&ent.batch_forward).unwrap();
        }

        stream.present(&mut device);
    }
}
<|endoftext|>


<commit_before><commit_msg>Add TB_ prefix to constants<commit_after><|endoftext|>


<commit_before><commit_msg>Inline stuff for Identity<commit_after><|endoftext|>


<commit_before>use rustc::middle::{const_eval, def_id, ty};
use rustc_mir::mir_map::MirMap;
use rustc_mir::repr::{self as mir, Mir};
use syntax::ast::Attribute;
use syntax::attr::AttrMetaMethods;

use std::iter;

const TRACE_EXECUTION: bool = false;

#[derive(Clone, Debug, PartialEq)]
enum Value {
    Uninit,
    Bool(bool),
    Int(i64), // FIXME(tsion): Should be bit-width aware.
    Adt { variant: usize, data_ptr: Pointer },
    Func(def_id::DefId),
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
enum Pointer {
    Stack(usize),
    // TODO(tsion): Heap
}

impl Pointer {
    fn offset(self, i: usize) -> Self {
        match self {
            Pointer::Stack(p) => Pointer::Stack(p + i),
        }
    }
}

/// A stack frame:
///
/// ```text
/// +-----------------------+
/// | Arg(0)                |
/// | Arg(1)                | arguments
/// | ...                   |
/// | Arg(num_args - 1)     |
/// + - - - - - - - - - - - +
/// | Var(0)                |
/// | Var(1)                | variables
/// | ...                   |
/// | Var(num_vars - 1)     |
/// + - - - - - - - - - - - +
/// | Temp(0)               |
/// | Temp(1)               | temporaries
/// | ...                   |
/// | Temp(num_temps - 1)   |
/// + - - - - - - - - - - - +
/// | Aggregates            | aggregates
/// +-----------------------+
/// ```
#[derive(Debug)]
struct Frame {
    return_ptr: Pointer,
    offset: usize,
    num_args: usize,
    num_vars: usize,
    num_temps: usize,
    num_aggregate_fields: usize,
}

impl Frame {
    fn size(&self) -> usize {
        self.num_args + self.num_vars + self.num_temps + self.num_aggregate_fields
    }

    fn arg_offset(&self, i: usize) -> usize {
        self.offset + i
    }

    fn var_offset(&self, i: usize) -> usize {
        self.offset + self.num_args + i
    }

    fn temp_offset(&self, i: usize) -> usize {
        self.offset + self.num_args + self.num_vars + i
    }
}

struct Interpreter<'a, 'tcx: 'a> {
    tcx: &'a ty::ctxt<'tcx>,
    mir_map: &'a MirMap<'tcx>,
    value_stack: Vec<Value>,
    call_stack: Vec<Frame>,
}

impl<'a, 'tcx> Interpreter<'a, 'tcx> {
    fn new(tcx: &'a ty::ctxt<'tcx>, mir_map: &'a MirMap<'tcx>) -> Self {
        Interpreter {
            tcx: tcx,
            mir_map: mir_map,
            value_stack: vec![Value::Uninit], // Allocate a spot for the top-level return value.
            call_stack: Vec::new(),
        }
    }

    fn push_stack_frame(&mut self, mir: &Mir, args: &[Value], return_ptr: Pointer) {
        let frame = Frame {
            return_ptr: return_ptr,
            offset: self.value_stack.len(),
            num_args: mir.arg_decls.len(),
            num_vars: mir.var_decls.len(),
            num_temps: mir.temp_decls.len(),
            num_aggregate_fields: 0,
        };

        self.value_stack.extend(iter::repeat(Value::Uninit).take(frame.size()));

        for (i, arg) in args.iter().enumerate() {
            self.value_stack[frame.arg_offset(i)] = arg.clone();
        }

        self.call_stack.push(frame);

    }

    fn pop_stack_frame(&mut self) {
        let frame = self.call_stack.pop().expect("tried to pop stack frame, but there were none");
        self.value_stack.truncate(frame.offset);
    }

    fn allocate_aggregate(&mut self, size: usize) -> Pointer {
        let frame = self.call_stack.last_mut().expect("missing call frame");
        frame.num_aggregate_fields += size;

        let ptr = Pointer::Stack(self.value_stack.len());
        self.value_stack.extend(iter::repeat(Value::Uninit).take(size));
        ptr
    }

    fn call(&mut self, mir: &Mir, args: &[Value], return_ptr: Pointer) {
        self.push_stack_frame(mir, args, return_ptr);
        let mut block = mir::START_BLOCK;

        loop {
            let block_data = mir.basic_block_data(block);

            for stmt in &block_data.statements {
                if TRACE_EXECUTION { println!("{:?}", stmt); }

                match stmt.kind {
                    mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
                        let ptr = self.eval_lvalue(lvalue);
                        let value = self.eval_rvalue(rvalue);
                        self.write_pointer(ptr, value);
                    }

                    mir::StatementKind::Drop(_kind, ref _lv) => {
                        // TODO
                    },
                }
            }

            if TRACE_EXECUTION { println!("{:?}", block_data.terminator); }

            match block_data.terminator {
                mir::Terminator::Return => break,
                mir::Terminator::Goto { target } => block = target,

                mir::Terminator::Call { ref data, targets } => {
                    let mir::CallData { ref destination, ref func, ref args } = *data;

                    let ptr = self.eval_lvalue(destination);
                    let func_val = self.eval_operand(func);

                    if let Value::Func(def_id) = func_val {
                        let node_id = self.tcx.map.as_local_node_id(def_id).unwrap();
                        let mir = &self.mir_map[&node_id];
                        let arg_vals: Vec<Value> =
                            args.iter().map(|arg| self.eval_operand(arg)).collect();

                        self.call(mir, &arg_vals, ptr);
                        block = targets[0];
                    } else {
                        panic!("tried to call a non-function value: {:?}", func_val);
                    }
                }

                mir::Terminator::If { ref cond, targets } => {
                    match self.eval_operand(cond) {
                        Value::Bool(true) => block = targets[0],
                        Value::Bool(false) => block = targets[1],
                        cond_val => panic!("Non-boolean `if` condition value: {:?}", cond_val),
                    }
                }

                mir::Terminator::SwitchInt { ref discr, ref values, ref targets, .. } => {
                    let discr_val = self.read_lvalue(discr);

                    let index = values.iter().position(|v| discr_val == self.eval_constant(v))
                        .expect("discriminant matched no values");

                    block = targets[index];
                }

                mir::Terminator::Switch { ref discr, ref targets, .. } => {
                    let discr_val = self.read_lvalue(discr);

                    if let Value::Adt { variant, .. } = discr_val {
                        block = targets[variant];
                    } else {
                        panic!("Switch on non-Adt value: {:?}", discr_val);
                    }
                }

                // mir::Terminator::Diverge => unimplemented!(),
                // mir::Terminator::Panic { target } => unimplemented!(),
                _ => unimplemented!(),
            }
        }

        self.pop_stack_frame();
    }

    fn eval_lvalue(&self, lvalue: &mir::Lvalue) -> Pointer {
        let frame = self.call_stack.last().expect("missing call frame");

        match *lvalue {
            mir::Lvalue::ReturnPointer => frame.return_ptr,
            mir::Lvalue::Arg(i)  => Pointer::Stack(frame.arg_offset(i as usize)),
            mir::Lvalue::Var(i)  => Pointer::Stack(frame.var_offset(i as usize)),
            mir::Lvalue::Temp(i) => Pointer::Stack(frame.temp_offset(i as usize)),

            mir::Lvalue::Projection(ref proj) => {
                // proj.base: Lvalue
                // proj.elem: ProjectionElem<Operand>

                let base_ptr = self.eval_lvalue(&proj.base);

                match proj.elem {
                    mir::ProjectionElem::Field(field) => {
                        base_ptr.offset(field.index())
                    }

                    mir::ProjectionElem::Downcast(_, variant) => {
                        let adt_val = self.read_pointer(base_ptr);

                        match adt_val {
                            Value::Adt { variant: actual_variant, data_ptr } => {
                                debug_assert_eq!(variant, actual_variant);
                                data_ptr
                            }

                            _ => panic!("Downcast attempted on non-Adt: {:?}", adt_val),
                        }
                    }

                    mir::ProjectionElem::Deref => unimplemented!(),
                    mir::ProjectionElem::Index(ref _operand) => unimplemented!(),
                    mir::ProjectionElem::ConstantIndex { .. } => unimplemented!(),
                }
            }

            _ => unimplemented!(),
        }
    }

    fn eval_binary_op(&mut self, bin_op: mir::BinOp, left: Value, right: Value) -> Value {
        match (left, right) {
            (Value::Int(l), Value::Int(r)) => {
                match bin_op {
                    mir::BinOp::Add    => Value::Int(l + r),
                    mir::BinOp::Sub    => Value::Int(l - r),
                    mir::BinOp::Mul    => Value::Int(l * r),
                    mir::BinOp::Div    => Value::Int(l / r),
                    mir::BinOp::Rem    => Value::Int(l % r),
                    mir::BinOp::BitXor => Value::Int(l ^ r),
                    mir::BinOp::BitAnd => Value::Int(l & r),
                    mir::BinOp::BitOr  => Value::Int(l | r),
                    mir::BinOp::Shl    => Value::Int(l << r),
                    mir::BinOp::Shr    => Value::Int(l >> r),
                    mir::BinOp::Eq     => Value::Bool(l == r),
                    mir::BinOp::Lt     => Value::Bool(l < r),
                    mir::BinOp::Le     => Value::Bool(l <= r),
                    mir::BinOp::Ne     => Value::Bool(l != r),
                    mir::BinOp::Ge     => Value::Bool(l >= r),
                    mir::BinOp::Gt     => Value::Bool(l > r),
                }
            }

            _ => unimplemented!(),
        }
    }

    fn eval_rvalue(&mut self, rvalue: &mir::Rvalue) -> Value {
        match *rvalue {
            mir::Rvalue::Use(ref operand) => self.eval_operand(operand),

            mir::Rvalue::BinaryOp(bin_op, ref left, ref right) => {
                let left_val = self.eval_operand(left);
                let right_val = self.eval_operand(right);
                self.eval_binary_op(bin_op, left_val, right_val)
            }

            mir::Rvalue::UnaryOp(un_op, ref operand) => {
                match (un_op, self.eval_operand(operand)) {
                    (mir::UnOp::Not, Value::Int(n)) => Value::Int(!n),
                    (mir::UnOp::Neg, Value::Int(n)) => Value::Int(-n),
                    _ => unimplemented!(),
                }
            }

            mir::Rvalue::Aggregate(mir::AggregateKind::Adt(ref adt_def, variant, _substs),
                                   ref operands) => {
                let max_fields = adt_def.variants
                    .iter()
                    .map(|v| v.fields.len())
                    .max()
                    .unwrap_or(0);

                let ptr = self.allocate_aggregate(max_fields);

                for (i, operand) in operands.iter().enumerate() {
                    let val = self.eval_operand(operand);
                    self.write_pointer(ptr.offset(i), val);
                }

                Value::Adt { variant: variant, data_ptr: ptr }
            }

            _ => unimplemented!(),
        }
    }

    fn eval_operand(&mut self, op: &mir::Operand) -> Value {
        match *op {
            mir::Operand::Consume(ref lvalue) => self.read_lvalue(lvalue),

            mir::Operand::Constant(ref constant) => {
                match constant.literal {
                    mir::Literal::Value { ref value } => self.eval_constant(value),

                    mir::Literal::Item { def_id, substs: _ } => {
                        // FIXME(tsion): Only items of function type shoud be wrapped into Func
                        // values. One test currently fails because a unit-like enum variant gets
                        // wrapped into Func here instead of a Value::Adt.
                        Value::Func(def_id)
                    }
                }
            }
        }
    }

    fn eval_constant(&self, const_val: &const_eval::ConstVal) -> Value {
        match *const_val {
            const_eval::ConstVal::Float(_f)         => unimplemented!(),
            const_eval::ConstVal::Int(i)            => Value::Int(i),
            const_eval::ConstVal::Uint(_u)          => unimplemented!(),
            const_eval::ConstVal::Str(ref _s)       => unimplemented!(),
            const_eval::ConstVal::ByteStr(ref _bs)  => unimplemented!(),
            const_eval::ConstVal::Bool(b)           => Value::Bool(b),
            const_eval::ConstVal::Struct(_node_id)  => unimplemented!(),
            const_eval::ConstVal::Tuple(_node_id)   => unimplemented!(),
            const_eval::ConstVal::Function(_def_id) => unimplemented!(),
        }
    }

    fn read_lvalue(&self, lvalue: &mir::Lvalue) -> Value {
        self.read_pointer(self.eval_lvalue(lvalue))
    }

    fn read_pointer(&self, p: Pointer) -> Value {
        match p {
            Pointer::Stack(offset) => self.value_stack[offset].clone(),
        }
    }

    fn write_pointer(&mut self, p: Pointer, val: Value) {
        match p {
            Pointer::Stack(offset) => self.value_stack[offset] = val,
        }
    }
}

pub fn interpret_start_points<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &MirMap<'tcx>) {
    for (&id, mir) in mir_map {
        for attr in tcx.map.attrs(id) {
            if attr.check_name("miri_run") {
                let item = tcx.map.expect_item(id);

                println!("Interpreting: {}", item.name);

                let mut interpreter = Interpreter::new(tcx, mir_map);
                let return_ptr = Pointer::Stack(0);
                interpreter.call(mir, &[], return_ptr);

                let val_str = format!("{:?}", interpreter.read_pointer(return_ptr));
                if !check_expected(&val_str, attr) {
                    println!("=> {}\n", val_str);
                }
            }
        }
    }
}

fn check_expected(actual: &str, attr: &Attribute) -> bool {
    if let Some(meta_items) = attr.meta_item_list() {
        for meta_item in meta_items {
            if meta_item.check_name("expected") {
                let expected = meta_item.value_str().unwrap();

                if actual == &expected[..] {
                    println!("Test passed!\n");
                } else {
                    println!("Actual value:\t{}\nExpected value:\t{}\n", actual, expected);
                }

                return true;
            }
        }
    }

    false
}
<commit_msg>Update for changes in rustc.<commit_after>use rustc::middle::{const_eval, def_id, ty};
use rustc::mir::repr::{self as mir, Mir};
use rustc_mir::mir_map::MirMap;
use syntax::ast::Attribute;
use syntax::attr::AttrMetaMethods;

use std::iter;

const TRACE_EXECUTION: bool = false;

#[derive(Clone, Debug, PartialEq)]
enum Value {
    Uninit,
    Bool(bool),
    Int(i64), // FIXME(tsion): Should be bit-width aware.
    Adt { variant: usize, data_ptr: Pointer },
    Func(def_id::DefId),
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
enum Pointer {
    Stack(usize),
    // TODO(tsion): Heap
}

impl Pointer {
    fn offset(self, i: usize) -> Self {
        match self {
            Pointer::Stack(p) => Pointer::Stack(p + i),
        }
    }
}

/// A stack frame:
///
/// ```text
/// +-----------------------+
/// | Arg(0)                |
/// | Arg(1)                | arguments
/// | ...                   |
/// | Arg(num_args - 1)     |
/// + - - - - - - - - - - - +
/// | Var(0)                |
/// | Var(1)                | variables
/// | ...                   |
/// | Var(num_vars - 1)     |
/// + - - - - - - - - - - - +
/// | Temp(0)               |
/// | Temp(1)               | temporaries
/// | ...                   |
/// | Temp(num_temps - 1)   |
/// + - - - - - - - - - - - +
/// | Aggregates            | aggregates
/// +-----------------------+
/// ```
#[derive(Debug)]
struct Frame {
    return_ptr: Pointer,
    offset: usize,
    num_args: usize,
    num_vars: usize,
    num_temps: usize,
    num_aggregate_fields: usize,
}

impl Frame {
    fn size(&self) -> usize {
        self.num_args + self.num_vars + self.num_temps + self.num_aggregate_fields
    }

    fn arg_offset(&self, i: usize) -> usize {
        self.offset + i
    }

    fn var_offset(&self, i: usize) -> usize {
        self.offset + self.num_args + i
    }

    fn temp_offset(&self, i: usize) -> usize {
        self.offset + self.num_args + self.num_vars + i
    }
}

struct Interpreter<'a, 'tcx: 'a> {
    tcx: &'a ty::ctxt<'tcx>,
    mir_map: &'a MirMap<'tcx>,
    value_stack: Vec<Value>,
    call_stack: Vec<Frame>,
}

impl<'a, 'tcx> Interpreter<'a, 'tcx> {
    fn new(tcx: &'a ty::ctxt<'tcx>, mir_map: &'a MirMap<'tcx>) -> Self {
        Interpreter {
            tcx: tcx,
            mir_map: mir_map,
            value_stack: vec![Value::Uninit], // Allocate a spot for the top-level return value.
            call_stack: Vec::new(),
        }
    }

    fn push_stack_frame(&mut self, mir: &Mir, args: &[Value], return_ptr: Pointer) {
        let frame = Frame {
            return_ptr: return_ptr,
            offset: self.value_stack.len(),
            num_args: mir.arg_decls.len(),
            num_vars: mir.var_decls.len(),
            num_temps: mir.temp_decls.len(),
            num_aggregate_fields: 0,
        };

        self.value_stack.extend(iter::repeat(Value::Uninit).take(frame.size()));

        for (i, arg) in args.iter().enumerate() {
            self.value_stack[frame.arg_offset(i)] = arg.clone();
        }

        self.call_stack.push(frame);

    }

    fn pop_stack_frame(&mut self) {
        let frame = self.call_stack.pop().expect("tried to pop stack frame, but there were none");
        self.value_stack.truncate(frame.offset);
    }

    fn allocate_aggregate(&mut self, size: usize) -> Pointer {
        let frame = self.call_stack.last_mut().expect("missing call frame");
        frame.num_aggregate_fields += size;

        let ptr = Pointer::Stack(self.value_stack.len());
        self.value_stack.extend(iter::repeat(Value::Uninit).take(size));
        ptr
    }

    fn call(&mut self, mir: &Mir, args: &[Value], return_ptr: Pointer) {
        self.push_stack_frame(mir, args, return_ptr);
        let mut block = mir::START_BLOCK;

        loop {
            let block_data = mir.basic_block_data(block);

            for stmt in &block_data.statements {
                if TRACE_EXECUTION { println!("{:?}", stmt); }

                match stmt.kind {
                    mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
                        let ptr = self.eval_lvalue(lvalue);
                        let value = self.eval_rvalue(rvalue);
                        self.write_pointer(ptr, value);
                    }

                    mir::StatementKind::Drop(_kind, ref _lv) => {
                        // TODO
                    },
                }
            }

            if TRACE_EXECUTION { println!("{:?}", block_data.terminator); }

            match block_data.terminator {
                mir::Terminator::Return => break,
                mir::Terminator::Goto { target } => block = target,

                mir::Terminator::Call { ref data, targets } => {
                    let mir::CallData { ref destination, ref func, ref args } = *data;

                    let ptr = self.eval_lvalue(destination);
                    let func_val = self.eval_operand(func);

                    if let Value::Func(def_id) = func_val {
                        let node_id = self.tcx.map.as_local_node_id(def_id).unwrap();
                        let mir = &self.mir_map[&node_id];
                        let arg_vals: Vec<Value> =
                            args.iter().map(|arg| self.eval_operand(arg)).collect();

                        self.call(mir, &arg_vals, ptr);
                        block = targets[0];
                    } else {
                        panic!("tried to call a non-function value: {:?}", func_val);
                    }
                }

                mir::Terminator::If { ref cond, targets } => {
                    match self.eval_operand(cond) {
                        Value::Bool(true) => block = targets[0],
                        Value::Bool(false) => block = targets[1],
                        cond_val => panic!("Non-boolean `if` condition value: {:?}", cond_val),
                    }
                }

                mir::Terminator::SwitchInt { ref discr, ref values, ref targets, .. } => {
                    let discr_val = self.read_lvalue(discr);

                    let index = values.iter().position(|v| discr_val == self.eval_constant(v))
                        .expect("discriminant matched no values");

                    block = targets[index];
                }

                mir::Terminator::Switch { ref discr, ref targets, .. } => {
                    let discr_val = self.read_lvalue(discr);

                    if let Value::Adt { variant, .. } = discr_val {
                        block = targets[variant];
                    } else {
                        panic!("Switch on non-Adt value: {:?}", discr_val);
                    }
                }

                // mir::Terminator::Diverge => unimplemented!(),
                // mir::Terminator::Panic { target } => unimplemented!(),
                _ => unimplemented!(),
            }
        }

        self.pop_stack_frame();
    }

    fn eval_lvalue(&self, lvalue: &mir::Lvalue) -> Pointer {
        let frame = self.call_stack.last().expect("missing call frame");

        match *lvalue {
            mir::Lvalue::ReturnPointer => frame.return_ptr,
            mir::Lvalue::Arg(i)  => Pointer::Stack(frame.arg_offset(i as usize)),
            mir::Lvalue::Var(i)  => Pointer::Stack(frame.var_offset(i as usize)),
            mir::Lvalue::Temp(i) => Pointer::Stack(frame.temp_offset(i as usize)),

            mir::Lvalue::Projection(ref proj) => {
                // proj.base: Lvalue
                // proj.elem: ProjectionElem<Operand>

                let base_ptr = self.eval_lvalue(&proj.base);

                match proj.elem {
                    mir::ProjectionElem::Field(field) => {
                        base_ptr.offset(field.index())
                    }

                    mir::ProjectionElem::Downcast(_, variant) => {
                        let adt_val = self.read_pointer(base_ptr);

                        match adt_val {
                            Value::Adt { variant: actual_variant, data_ptr } => {
                                debug_assert_eq!(variant, actual_variant);
                                data_ptr
                            }

                            _ => panic!("Downcast attempted on non-Adt: {:?}", adt_val),
                        }
                    }

                    mir::ProjectionElem::Deref => unimplemented!(),
                    mir::ProjectionElem::Index(ref _operand) => unimplemented!(),
                    mir::ProjectionElem::ConstantIndex { .. } => unimplemented!(),
                }
            }

            _ => unimplemented!(),
        }
    }

    fn eval_binary_op(&mut self, bin_op: mir::BinOp, left: Value, right: Value) -> Value {
        match (left, right) {
            (Value::Int(l), Value::Int(r)) => {
                match bin_op {
                    mir::BinOp::Add    => Value::Int(l + r),
                    mir::BinOp::Sub    => Value::Int(l - r),
                    mir::BinOp::Mul    => Value::Int(l * r),
                    mir::BinOp::Div    => Value::Int(l / r),
                    mir::BinOp::Rem    => Value::Int(l % r),
                    mir::BinOp::BitXor => Value::Int(l ^ r),
                    mir::BinOp::BitAnd => Value::Int(l & r),
                    mir::BinOp::BitOr  => Value::Int(l | r),
                    mir::BinOp::Shl    => Value::Int(l << r),
                    mir::BinOp::Shr    => Value::Int(l >> r),
                    mir::BinOp::Eq     => Value::Bool(l == r),
                    mir::BinOp::Lt     => Value::Bool(l < r),
                    mir::BinOp::Le     => Value::Bool(l <= r),
                    mir::BinOp::Ne     => Value::Bool(l != r),
                    mir::BinOp::Ge     => Value::Bool(l >= r),
                    mir::BinOp::Gt     => Value::Bool(l > r),
                }
            }

            _ => unimplemented!(),
        }
    }

    fn eval_rvalue(&mut self, rvalue: &mir::Rvalue) -> Value {
        match *rvalue {
            mir::Rvalue::Use(ref operand) => self.eval_operand(operand),

            mir::Rvalue::BinaryOp(bin_op, ref left, ref right) => {
                let left_val = self.eval_operand(left);
                let right_val = self.eval_operand(right);
                self.eval_binary_op(bin_op, left_val, right_val)
            }

            mir::Rvalue::UnaryOp(un_op, ref operand) => {
                match (un_op, self.eval_operand(operand)) {
                    (mir::UnOp::Not, Value::Int(n)) => Value::Int(!n),
                    (mir::UnOp::Neg, Value::Int(n)) => Value::Int(-n),
                    _ => unimplemented!(),
                }
            }

            mir::Rvalue::Aggregate(mir::AggregateKind::Adt(ref adt_def, variant, _substs),
                                   ref operands) => {
                let max_fields = adt_def.variants
                    .iter()
                    .map(|v| v.fields.len())
                    .max()
                    .unwrap_or(0);

                let ptr = self.allocate_aggregate(max_fields);

                for (i, operand) in operands.iter().enumerate() {
                    let val = self.eval_operand(operand);
                    self.write_pointer(ptr.offset(i), val);
                }

                Value::Adt { variant: variant, data_ptr: ptr }
            }

            _ => unimplemented!(),
        }
    }

    fn eval_operand(&mut self, op: &mir::Operand) -> Value {
        match *op {
            mir::Operand::Consume(ref lvalue) => self.read_lvalue(lvalue),

            mir::Operand::Constant(ref constant) => {
                match constant.literal {
                    mir::Literal::Value { ref value } => self.eval_constant(value),

                    mir::Literal::Item { def_id, substs: _ } => {
                        // FIXME(tsion): Only items of function type should be wrapped into Func
                        // values. One test currently fails because a unit-like enum variant gets
                        // wrapped into Func here instead of a Value::Adt.
                        Value::Func(def_id)
                    }
                }
            }
        }
    }

    fn eval_constant(&self, const_val: &const_eval::ConstVal) -> Value {
        match *const_val {
            const_eval::ConstVal::Float(_f)         => unimplemented!(),
            const_eval::ConstVal::Int(i)            => Value::Int(i),
            const_eval::ConstVal::Uint(_u)          => unimplemented!(),
            const_eval::ConstVal::Str(ref _s)       => unimplemented!(),
            const_eval::ConstVal::ByteStr(ref _bs)  => unimplemented!(),
            const_eval::ConstVal::Bool(b)           => Value::Bool(b),
            const_eval::ConstVal::Struct(_node_id)  => unimplemented!(),
            const_eval::ConstVal::Tuple(_node_id)   => unimplemented!(),
            const_eval::ConstVal::Function(_def_id) => unimplemented!(),
            const_eval::ConstVal::Array(_, _)       => unimplemented!(),
            const_eval::ConstVal::Repeat(_, _)      => unimplemented!(),
        }
    }

    fn read_lvalue(&self, lvalue: &mir::Lvalue) -> Value {
        self.read_pointer(self.eval_lvalue(lvalue))
    }

    fn read_pointer(&self, p: Pointer) -> Value {
        match p {
            Pointer::Stack(offset) => self.value_stack[offset].clone(),
        }
    }

    fn write_pointer(&mut self, p: Pointer, val: Value) {
        match p {
            Pointer::Stack(offset) => self.value_stack[offset] = val,
        }
    }
}

pub fn interpret_start_points<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &MirMap<'tcx>) {
    for (&id, mir) in mir_map {
        for attr in tcx.map.attrs(id) {
            if attr.check_name("miri_run") {
                let item = tcx.map.expect_item(id);

                println!("Interpreting: {}", item.name);

                let mut interpreter = Interpreter::new(tcx, mir_map);
                let return_ptr = Pointer::Stack(0);
                interpreter.call(mir, &[], return_ptr);

                let val_str = format!("{:?}", interpreter.read_pointer(return_ptr));
                if !check_expected(&val_str, attr) {
                    println!("=> {}\n", val_str);
                }
            }
        }
    }
}

fn check_expected(actual: &str, attr: &Attribute) -> bool {
    if let Some(meta_items) = attr.meta_item_list() {
        for meta_item in meta_items {
            if meta_item.check_name("expected") {
                let expected = meta_item.value_str().unwrap();

                if actual == &expected[..] {
                    println!("Test passed!\n");
                } else {
                    println!("Actual value:\t{}\nExpected value:\t{}\n", actual, expected);
                }

                return true;
            }
        }
    }

    false
}
<|endoftext|>


<commit_before><commit_msg>Add test for #11677<commit_after>// Copyright 2014 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.

#![allow(dead_code)]

// this code used to cause an ICE

trait X<T> {}

struct S<T> {f: Box<X<T>>, g: Box<X<T>>}

struct F;
impl X<int> for F {}

fn main() {
  S {f: box F, g: box F};
}
<|endoftext|>


<commit_before><commit_msg>Adds a test for #48070<commit_after>// Copyright 2018 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.

// revisions: lxl nll

#![cfg_attr(nll, feature(nll))]

struct Foo {
    x: u32
}

impl Foo {
    fn twiddle(&mut self) -> &mut Self { self }
    fn twaddle(&mut self) -> &mut Self { self }
    fn emit(&mut self) {
        self.x += 1;
    }
}

fn main() {
    let mut foo = Foo { x: 0 };
    match 22 {
        22 => &mut foo,
        44 => foo.twiddle(),
        _ => foo.twaddle(),
    }.emit();
}
<|endoftext|>


<commit_before><commit_msg>Correctly parse statements with multiple escaped characters (#292)<commit_after><|endoftext|>


<commit_before><commit_msg>alpha-equivalence + modernizing the format for matches<commit_after><|endoftext|>


<commit_before><commit_msg>add a benchmark for arithmetic expressions<commit_after>#![feature(test)]
extern crate test;

#[macro_use]
extern crate nom;

use test::Bencher;
use nom::{IResult,digit};

// Parser definition

use std::str;
use std::str::FromStr;

// We parse any expr surrounded by parens, ignoring all whitespaces around those
named!(parens<i64>, ws!(delimited!( tag!("("), expr, tag!(")") )) );

// We transform an integer string into a i64, ignoring surrounding whitespaces
// We look for a digit suite, and try to convert it.
// If either str::from_utf8 or FromStr::from_str fail,
// we fallback to the parens parser defined above
named!(factor<i64>, alt!(
    map_res!(
      map_res!(
        ws!(digit),
        str::from_utf8
      ),
      FromStr::from_str
    )
  | parens
  )
);

// We read an initial factor and for each time we find
// a * or / operator followed by another factor, we do
// the math by folding everything
named!(term <i64>, do_parse!(
    init: factor >>
    res:  fold_many0!(
        pair!(alt!(tag!("*") | tag!("/")), factor),
        init,
        |acc, (op, val): (&[u8], i64)| {
            if (op[0] as char) == '*' { acc * val } else { acc / val }
        }
    ) >>
    (res)
  )
);

named!(expr <i64>, do_parse!(
    init: term >>
    res:  fold_many0!(
        pair!(alt!(tag!("+") | tag!("-")), term),
        init,
        |acc, (op, val): (&[u8], i64)| {
            if (op[0] as char) == '+' { acc + val } else { acc - val }
        }
    ) >>
    (res)
  )
);

#[bench]
fn arithmetic(b: &mut Bencher) {
  let data = &b"  2*2 / ( 5 - 1) + 3 / 4 * (2 - 7 + 567 *12 /2) + 3*(1+2*( 45 /2))";

  println!("parsed:\n{:?}", expr(&data[..]));
  b.iter(||{
    expr(&data[..])
  });
}

<|endoftext|>


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

#![allow(dead_code)]
#![allow(unused_unsafe)]

use std::marker::Sync;

struct Foo {
    a: uint,
    b: *const ()
}

unsafe impl Sync for Foo {}

fn foo<T>(a: T) -> T {
    a
}

static BLOCK_INTEGRAL: uint = { 1 };
static BLOCK_EXPLICIT_UNIT: () = { () };
static BLOCK_IMPLICIT_UNIT: () = { };
static BLOCK_FLOAT: f64 = { 1.0 };
static BLOCK_ENUM: Option<uint> = { Some(100) };
static BLOCK_STRUCT: Foo = { Foo { a: 12, b: 0 as *const () } };
static BLOCK_UNSAFE: uint = unsafe { 1000 };

// FIXME: #13970
// static BLOCK_FN_INFERRED: fn(uint) -> uint = { foo };

// FIXME: #13971
// static BLOCK_FN: fn(uint) -> uint = { foo::<uint> };

// FIXME: #13972
// static BLOCK_ENUM_CONSTRUCTOR: fn(uint) -> Option<uint> = { Some };

// FIXME: #13973
// static BLOCK_UNSAFE_SAFE_PTR: &'static int = unsafe { &*(0xdeadbeef as *int) };
// static BLOCK_UNSAFE_SAFE_PTR_2: &'static int = unsafe {
//     static X: *int = 0xdeadbeef as *int;
//     &*X
// };

pub fn main() {
    assert_eq!(BLOCK_INTEGRAL, 1);
    assert_eq!(BLOCK_EXPLICIT_UNIT, ());
    assert_eq!(BLOCK_IMPLICIT_UNIT, ());
    assert_eq!(BLOCK_FLOAT, 1.0_f64);
    assert_eq!(BLOCK_STRUCT.a, 12);
    assert_eq!(BLOCK_STRUCT.b, 0 as *const ());
    assert_eq!(BLOCK_ENUM, Some(100));
    assert_eq!(BLOCK_UNSAFE, 1000);

    // FIXME: #13970
    // assert_eq!(BLOCK_FN_INFERRED(300), 300);

    // FIXME: #13971
    // assert_eq!(BLOCK_FN(300), 300);

    // FIXME: #13972
    // assert_eq!(BLOCK_ENUM_CONSTRUCTOR(200), Some(200));

    // FIXME: #13973
    // assert_eq!(BLOCK_UNSAFE_SAFE_PTR as *int as uint, 0xdeadbeef_u);
    // assert_eq!(BLOCK_UNSAFE_SAFE_PTR_2 as *int as uint, 0xdeadbeef_u);
}
<commit_msg>tests: uncomment regression tests for 13970, 13971, 13972<commit_after>// Copyright 2014 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.

#![allow(dead_code)]
#![allow(unused_unsafe)]

use std::marker::Sync;

struct Foo {
    a: usize,
    b: *const ()
}

unsafe impl Sync for Foo {}

fn foo<T>(a: T) -> T {
    a
}

static BLOCK_INTEGRAL: usize = { 1 };
static BLOCK_EXPLICIT_UNIT: () = { () };
static BLOCK_IMPLICIT_UNIT: () = { };
static BLOCK_FLOAT: f64 = { 1.0 };
static BLOCK_ENUM: Option<usize> = { Some(100) };
static BLOCK_STRUCT: Foo = { Foo { a: 12, b: 0 as *const () } };
static BLOCK_UNSAFE: usize = unsafe { 1000 };

static BLOCK_FN_INFERRED: fn(usize) -> usize = { foo };

static BLOCK_FN: fn(usize) -> usize = { foo::<usize> };

static BLOCK_ENUM_CONSTRUCTOR: fn(usize) -> Option<usize> = { Some };

// FIXME #13972
// static BLOCK_UNSAFE_SAFE_PTR: &'static isize = unsafe { &*(0xdeadbeef as *const isize) };
// static BLOCK_UNSAFE_SAFE_PTR_2: &'static isize = unsafe {
//     const X: *const isize = 0xdeadbeef as *const isize;
//     &*X
// };

pub fn main() {
    assert_eq!(BLOCK_INTEGRAL, 1);
    assert_eq!(BLOCK_EXPLICIT_UNIT, ());
    assert_eq!(BLOCK_IMPLICIT_UNIT, ());
    assert_eq!(BLOCK_FLOAT, 1.0_f64);
    assert_eq!(BLOCK_STRUCT.a, 12);
    assert_eq!(BLOCK_STRUCT.b, 0 as *const ());
    assert_eq!(BLOCK_ENUM, Some(100));
    assert_eq!(BLOCK_UNSAFE, 1000);
    assert_eq!(BLOCK_FN_INFERRED(300), 300);
    assert_eq!(BLOCK_FN(300), 300);
    assert_eq!(BLOCK_ENUM_CONSTRUCTOR(200), Some(200));
    // FIXME #13972
    // assert_eq!(BLOCK_UNSAFE_SAFE_PTR as *const isize as usize, 0xdeadbeef_us);
    // assert_eq!(BLOCK_UNSAFE_SAFE_PTR_2 as *const isize as usize, 0xdeadbeef_us);
}
<|endoftext|>


<commit_before><commit_msg>Create user path once.<commit_after><|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.

/*!

Higher level communication abstractions.

*/

#[allow(missing_doc)];

use std::comm::{GenericChan, GenericSmartChan, GenericPort};
use std::comm::{Chan, Port, Peekable};
use std::comm;

/// An extension of `pipes::stream` that allows both sending and receiving.
pub struct DuplexStream<T, U> {
    priv chan: Chan<T>,
    priv port: Port<U>,
}

// Allow these methods to be used without import:
impl<T:Send,U:Send> DuplexStream<T, U> {
    pub fn send(&self, x: T) {
        self.chan.send(x)
    }
    pub fn try_send(&self, x: T) -> bool {
        self.chan.try_send(x)
    }
    pub fn recv(&self, ) -> U {
        self.port.recv()
    }
    pub fn try_recv(&self) -> Option<U> {
        self.port.try_recv()
    }
    pub fn peek(&self) -> bool {
        self.port.peek()
    }
}

impl<T:Send,U:Send> GenericChan<T> for DuplexStream<T, U> {
    fn send(&self, x: T) {
        self.chan.send(x)
    }
}

impl<T:Send,U:Send> GenericSmartChan<T> for DuplexStream<T, U> {
    fn try_send(&self, x: T) -> bool {
        self.chan.try_send(x)
    }
}

impl<T:Send,U:Send> GenericPort<U> for DuplexStream<T, U> {
    fn recv(&self) -> U {
        self.port.recv()
    }

    fn try_recv(&self) -> Option<U> {
        self.port.try_recv()
    }
}

impl<T:Send,U:Send> Peekable<U> for DuplexStream<T, U> {
    fn peek(&self) -> bool {
        self.port.peek()
    }
}

/// Creates a bidirectional stream.
pub fn DuplexStream<T:Send,U:Send>()
    -> (DuplexStream<T, U>, DuplexStream<U, T>)
{
    let (p1, c2) = comm::stream();
    let (p2, c1) = comm::stream();
    (DuplexStream {
        chan: c1,
        port: p1
    },
     DuplexStream {
         chan: c2,
         port: p2
     })
}

#[cfg(test)]
mod test {
    use comm::DuplexStream;

    #[test]
    pub fn DuplexStream1() {
        let (left, right) = DuplexStream();

        left.send(~"abc");
        right.send(123);

        assert!(left.recv() == 123);
        assert!(right.recv() == ~"abc");
    }
}
<commit_msg>auto merge of #8908 : tikue/rust/master, r=anasazi<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.

/*!

Higher level communication abstractions.

*/

#[allow(missing_doc)];

use std::comm::{GenericChan, GenericSmartChan, GenericPort};
use std::comm::{Chan, Port, Peekable};
use std::comm;

/// An extension of `pipes::stream` that allows both sending and receiving.
pub struct DuplexStream<T, U> {
    priv chan: Chan<T>,
    priv port: Port<U>,
}

// Allow these methods to be used without import:
impl<T:Send,U:Send> DuplexStream<T, U> {
    pub fn send(&self, x: T) {
        self.chan.send(x)
    }
    pub fn try_send(&self, x: T) -> bool {
        self.chan.try_send(x)
    }
    pub fn recv(&self, ) -> U {
        self.port.recv()
    }
    pub fn try_recv(&self) -> Option<U> {
        self.port.try_recv()
    }
    pub fn peek(&self) -> bool {
        self.port.peek()
    }
}

impl<T:Send,U:Send> GenericChan<T> for DuplexStream<T, U> {
    fn send(&self, x: T) {
        self.chan.send(x)
    }
}

impl<T:Send,U:Send> GenericSmartChan<T> for DuplexStream<T, U> {
    fn try_send(&self, x: T) -> bool {
        self.chan.try_send(x)
    }
}

impl<T:Send,U:Send> GenericPort<U> for DuplexStream<T, U> {
    fn recv(&self) -> U {
        self.port.recv()
    }

    fn try_recv(&self) -> Option<U> {
        self.port.try_recv()
    }
}

impl<T:Send,U:Send> Peekable<U> for DuplexStream<T, U> {
    fn peek(&self) -> bool {
        self.port.peek()
    }
}

/// Creates a bidirectional stream.
pub fn DuplexStream<T:Send,U:Send>()
    -> (DuplexStream<T, U>, DuplexStream<U, T>)
{
    let (p1, c2) = comm::stream();
    let (p2, c1) = comm::stream();
    (DuplexStream {
        chan: c1,
        port: p1
    },
     DuplexStream {
         chan: c2,
         port: p2
     })
}

/// An extension of `pipes::stream` that provides synchronous message sending.
pub struct SyncChan<T> { priv duplex_stream: DuplexStream<T, ()> }
/// An extension of `pipes::stream` that acknowledges each message received.
pub struct SyncPort<T> { priv duplex_stream: DuplexStream<(), T> }

impl<T: Send> GenericChan<T> for SyncChan<T> {
    fn send(&self, val: T) {
        assert!(self.try_send(val), "SyncChan.send: receiving port closed");
    }
}

impl<T: Send> GenericSmartChan<T> for SyncChan<T> {
    /// Sends a message, or report if the receiver has closed the connection before receiving.
    fn try_send(&self, val: T) -> bool {
        self.duplex_stream.try_send(val) && self.duplex_stream.try_recv().is_some()
    }
}

impl<T: Send> GenericPort<T> for SyncPort<T> {
    fn recv(&self) -> T {
        self.try_recv().expect("SyncPort.recv: sending channel closed")
    }

    fn try_recv(&self) -> Option<T> {
        do self.duplex_stream.try_recv().map_move |val| {
            self.duplex_stream.try_send(());
            val
        }
    }
}

impl<T: Send> Peekable<T> for SyncPort<T> {
    fn peek(&self) -> bool {
        self.duplex_stream.peek()
    }
}

/// Creates a stream whose channel, upon sending a message, blocks until the message is received.
pub fn rendezvous<T: Send>() -> (SyncPort<T>, SyncChan<T>) {
    let (chan_stream, port_stream) = DuplexStream();
    (SyncPort { duplex_stream: port_stream }, SyncChan { duplex_stream: chan_stream })
}

#[cfg(test)]
mod test {
    use comm::{DuplexStream, rendezvous};
    use std::rt::test::run_in_newsched_task;
    use std::task::spawn_unlinked;

    #[test]
    pub fn DuplexStream1() {
        let (left, right) = DuplexStream();

        left.send(~"abc");
        right.send(123);

        assert!(left.recv() == 123);
        assert!(right.recv() == ~"abc");
    }

    #[test]
    pub fn basic_rendezvous_test() {
        let (port, chan) = rendezvous();

        do spawn {
            chan.send("abc");
        }

        assert!(port.recv() == "abc");
    }

    #[test]
    fn recv_a_lot() {
        // Rendezvous streams should be able to handle any number of messages being sent
        do run_in_newsched_task {
            let (port, chan) = rendezvous();
            do spawn {
                do 1000000.times { chan.send(()) }
            }
            do 1000000.times { port.recv() }
        }
    }

    #[test]
    fn send_and_fail_and_try_recv() {
        let (port, chan) = rendezvous();
        do spawn_unlinked {
            chan.duplex_stream.send(()); // Can't access this field outside this module
            fail!()
        }
        port.recv()
    }

    #[test]
    fn try_send_and_recv_then_fail_before_ack() {
        let (port, chan) = rendezvous();
        do spawn_unlinked {
            port.duplex_stream.recv();
            fail!()
        }
        chan.try_send(());
    }

    #[test]
    #[should_fail]
    fn send_and_recv_then_fail_before_ack() {
        let (port, chan) = rendezvous();
        do spawn_unlinked {
            port.duplex_stream.recv();
            fail!()
        }
        chan.send(());
    }
}
<|endoftext|>