<commit_before>extern crate kernel32;
extern crate gdi32;
extern crate user32;
extern crate winapi;

#[macro_use]
extern crate vulkano;

use std::sync::Arc;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::mem;
use std::ptr;

fn main() {
    println!("{:?}", vulkano::instance::layers_list().unwrap().iter().map(|l| l.name().to_owned()).collect::<Vec<_>>());
    // The first step of any vulkan program is to create an instance.
    // TODO: for the moment the AMD driver crashes if you don't pass an ApplicationInfo, but in theory it's optional
    let app = vulkano::instance::ApplicationInfo { application_name: "test", application_version: 1, engine_name: "test", engine_version: 1 };
    let instance = vulkano::instance::Instance::new(Some(&app), &["VK_LAYER_LUNARG_mem_tracker"]).expect("failed to create instance");

    // We then choose which physical device to use.
    //
    // In a real application, there are three things to take into consideration:
    //
    // - Some devices support some optional features that may be required by your application.
    //   You should filter out the devices that don't support your app.
    //
    // - Not all devices can draw to a certain surface. Once you create your window, you have to
    //   choose a device that is capable of drawing to it.
    //
    // - You probably want to leave the choice between the remaining devices to the user.
    //
    // Here we are just going to use the first device.
    let physical = vulkano::instance::PhysicalDevice::enumerate(&instance)
                            .next().expect("no device available");
    println!("Using device: {} (type: {:?})", physical.name(), physical.ty());

    // The objective of this example is to draw a triangle on a window. To do so, we first have to
    // create the window in a platform-specific way. Then we create a `Surface` object from it.
    //
    // Surface objects are cross-platform. Once you have a `Surface` everything is the same again.
    let window = unsafe { create_window() };
    let surface = unsafe { vulkano::swapchain::Surface::from_hwnd(&instance, kernel32::GetModuleHandleW(ptr::null()), window).unwrap() };

    // The next step is to choose which queue will execute our draw commands.
    //
    // Devices can provide multiple queues to run things in parallel (for example a draw queue and
    // a compute queue). This is something you have to have to manage manually in Vulkan.
    //
    // We have to specify which queues you are going to use when we create the device, therefore
    // we need to choose that now.
    let queue = physical.queue_families().find(|q| q.supports_graphics() &&
                                                   surface.is_supported(q).unwrap_or(false))
                                                .expect("couldn't find a graphical queue family");

    // Now initializing the device.
    //
    // We have to pass a list of optional Vulkan features that must be enabled. TODO: explain this
    //
    // We also have to pass a list of queues to create and their priorities relative to each other.
    // Since we create one queue, we don't really care about the priority and just pass `0.5`.
    // The list of created queues is returned by the function alongside with the device.
    let (device, queues) = vulkano::device::Device::new(&physical, physical.supported_features(),
                                                        [(queue, 0.5)].iter().cloned(),
                                                        &["VK_LAYER_LUNARG_mem_tracker"])
                                                                .expect("failed to create device");

    // Since we can request multiple queues, the `queues` variable is a `Vec`. Our actual queue
    // is the first element.
    let queue = queues.into_iter().next().unwrap();

    // Before we can draw on the surface, we have to create what is called a swapchain. Creating
    // a swapchain allocates the color buffers that will contain the image that will ultimately
    // be visible on the screen. These images are returned alongside with the swapchain.
    let (swapchain, images) = {
        let caps = surface.get_capabilities(&physical).expect("failed to get surface capabilities");

        let dimensions = caps.current_extent.unwrap_or([1280, 1024]);
        let present = caps.present_modes[0];
        let usage = caps.supported_usage_flags;

        vulkano::swapchain::Swapchain::new(&device, &surface, 3,
                                           vulkano::formats::B8G8R8A8Srgb, dimensions, 1,
                                           &usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
                                           vulkano::swapchain::CompositeAlpha::Opaque,
                                           present, true).expect("failed to create swapchain")
    };

    // We now create a buffer that will store the shape of our triangle.
    //
    // The first parameter is the device to use, and the second parameter is how the buffer will
    // be used on the GPU side. This is a vertex buffer, and we need to tell this to the
    // implementation.
    //
    // The third parameter is where to get the memory where the buffer will be stored. It is very
    // important as it also determines the way you are going to access and modify your buffer.
    // Here we just ask for a basic host visible memory.
    //
    // Note that to store immutable data, the best way is to create two buffers. One buffer on
    // the CPU and one buffer on the GPU. We then write our data to the buffer on the CPU and
    // ask the GPU to copy it to the real buffer. This way the data is located on the most
    // efficient memory possible.
    let vertex_buffer: Arc<vulkano::buffer::Buffer<[Vertex; 3], _>> =
                                vulkano::buffer::Buffer::new(&device, &vulkano::buffer::Usage::all(),
                                                             vulkano::memory::HostVisible, &queue)
                                                                .expect("failed to create buffer");
    struct Vertex { position: [f32; 2] }
    impl_vertex!(Vertex, position);

    // The buffer that we created contains uninitialized data.
    // In order to fill it with data, we have to *map* it.
    {
        // The `try_write` function would return `None` if the buffer was in use by the GPU. This
        // obviously can't happen here, since we haven't ask the GPU to do anything yet.
        let mut mapping = vertex_buffer.try_write().unwrap();
        mapping[0].position = [-0.5, -0.25];
        mapping[1].position = [0.0, 0.5];
        mapping[2].position = [0.25, -0.1];
    }

    // The next step is to create the shaders.
    //
    // The shader creation API provided by the vulkano library is unsafe, for various reasons.
    //
    // Instead, in our build script we used the `vulkano-shaders` crate to parse our shaders at
    // compile time and provide a safe wrapper over vulkano's API. You can find the shaders'
    // source code in the `triangle_fs.glsl` and `triangle_vs.glsl` files.
    //
    // The code generated by the build script created a struct named `TriangleShader`, which we
    // can now use to load the shader.
    //
    // Because of some restrictions with the `include!` macro, we need to use a module.
    mod vs { include!{concat!(env!("OUT_DIR"), "/examples-triangle_vs.rs")} }
    let vs = vs::TriangleShader::load(&device).expect("failed to create shader module");
    mod fs { include!{concat!(env!("OUT_DIR"), "/examples-triangle_fs.rs")} }
    let fs = fs::TriangleShader::load(&device).expect("failed to create shader module");

    // At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL
    // implicitely does a lot of computation whenever you draw. In Vulkan, you have to do all this
    // manually.

    // We are going to create a command buffer below. Command buffers need to be allocated
    // from a *command buffer pool*, so we create the pool.
    let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.lock().unwrap().family())
                                                  .expect("failed to create command buffer pool");

    // We are going to draw on the images returned when creating the swapchain. To do so, we must
    // convert them into *image views*. TODO: explain more
    let images = images.into_iter().map(|image| {
        let image = image.transition(vulkano::image::Layout::PresentSrc, &cb_pool,
                                     &mut queue.lock().unwrap()).unwrap();
        vulkano::image::ImageView::new(&image).expect("failed to create image view")
    }).collect::<Vec<_>>();

    // The next step is to create a *renderpass*, which is an object that describes where the
    // output of the graphics pipeline will go. It describes the layout of the images
    // where the colors, depth and/or stencil information will be written.
    let renderpass = renderpass!{
        device: &device,
        attachments: {
            color [Clear]
        }
    }.unwrap();

    let pipeline: Arc<vulkano::pipeline::GraphicsPipeline<Arc<vulkano::buffer::Buffer<[Vertex; 3], _>>>> = {
        let ia = vulkano::pipeline::input_assembly::InputAssembly {
            topology: vulkano::pipeline::input_assembly::PrimitiveTopology::TriangleList,
            primitive_restart_enable: false,
        };

        let raster = Default::default();
        let ms = vulkano::pipeline::multisample::Multisample::disabled();
        let blend = vulkano::pipeline::blend::Blend {
            logic_op: None,
            blend_constants: Some([0.0; 4]),
        };

        let viewports = vulkano::pipeline::viewport::ViewportsState::Fixed {
            data: vec![(
                vulkano::pipeline::viewport::Viewport {
                    origin: [0.0, 0.0],
                    dimensions: [1244.0, 699.0],
                    depth_range: 0.0 .. 1.0
                },
                vulkano::pipeline::viewport::Scissor {
                    origin: [0, 0],
                    dimensions: [1244, 699],
                }
            )],
        };

        vulkano::pipeline::GraphicsPipeline::new(&device, &vs.main_entry_point(), &ia, &viewports,
                                                 &raster, &ms, &blend, &fs.main_entry_point(),
                                                 &renderpass.subpass(0).unwrap()).unwrap()
    };

    // The renderpass we created above only describes the layout of our framebuffers. We also need
    // to create the actual framebuffers.
    //
    // Since we need to draw to multiple images, we are going to create a different framebuffer for
    // each image.
    let framebuffers = images.iter().map(|image| {
        vulkano::framebuffer::Framebuffer::new(&renderpass, (1244, 699, 1), image).unwrap()
    }).collect::<Vec<_>>();

    // The final initialization step is to create a command buffer.
    //
    // A command buffer contains a list of commands that the GPU must execute. This can include
    // transfers between buffers, clearing images or attachments, etc. and draw commands. Here we
    // create a command buffer with a single command: drawing the triangle. The color attachment
    // is also cleared at the start.
    //
    // Since we have several images to draw on, we are also going to create one command buffer for
    // each image.
    let command_buffers = framebuffers.iter().map(|framebuffer| {
        vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
            .draw_inline(&renderpass, &framebuffer, [0.0, 0.0, 1.0, 1.0])
            .draw(&pipeline, vertex_buffer.clone(), &vulkano::command_buffer::DynamicState::none())
            .draw_end()
            .build().unwrap()
    }).collect::<Vec<_>>();

    // Initialization is finally finished!

    // Note that the only thing we need now are the `command_buffers` and `swapchain` variables.
    // Everything else is kept alive internally with `Arc`s (even the vertex buffer for example),
    // so the only variable that we need is this one.

    loop {
        // Before we can draw on the output, we have to *acquire* an image from the swapchain.
        // This operation returns the index of the image that we are allowed to draw upon..
        let image_num = swapchain.acquire_next_image().unwrap();

        // Our queue is wrapped around a `Mutex`, so we have to lock it.
        let mut queue = queue.lock().unwrap();

        // In order to draw, all we need to do is submit the command buffer to the queue.
        command_buffers[image_num].submit(&mut queue).unwrap();

        // The color output should now contain our triangle. But in order to show it on the
        // screen, we have to *present* the image. Depending on the presentation mode, this may
        // be shown immediatly or on the next redraw.
        swapchain.present(&mut queue, image_num).unwrap();

        // In a real application we want to submit things to the same queue in parallel, so we
        // shouldn't keep it locked too long.
        drop(queue);

        unsafe {
            let mut msg = mem::uninitialized();
            if user32::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) == 0 {
                break;
            }

            user32::TranslateMessage(&msg);
            user32::DispatchMessageW(&msg);
        }
    }
}

unsafe fn create_window() -> winapi::HWND {
    let class_name = register_window_class();

    let title: Vec<u16> = vec![b'V' as u16, b'u' as u16, b'l' as u16, b'k' as u16,
                               b'a' as u16, b'n' as u16, 0];

    user32::CreateWindowExW(winapi::WS_EX_APPWINDOW | winapi::WS_EX_WINDOWEDGE, class_name.as_ptr(),
                            title.as_ptr() as winapi::LPCWSTR,
                            winapi::WS_OVERLAPPEDWINDOW | winapi::WS_CLIPSIBLINGS |
                            winapi::WS_VISIBLE,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            ptr::null_mut(), ptr::null_mut(),
                            kernel32::GetModuleHandleW(ptr::null()),
                            ptr::null_mut())
}

unsafe fn register_window_class() -> Vec<u16> {
    let class_name: Vec<u16> = OsStr::new("Window Class").encode_wide().chain(Some(0).into_iter())
                                                         .collect::<Vec<u16>>();

    let class = winapi::WNDCLASSEXW {
        cbSize: mem::size_of::<winapi::WNDCLASSEXW>() as winapi::UINT,
        style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
        lpfnWndProc: Some(callback),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: kernel32::GetModuleHandleW(ptr::null()),
        hIcon: ptr::null_mut(),
        hCursor: ptr::null_mut(),
        hbrBackground: ptr::null_mut(),
        lpszMenuName: ptr::null(),
        lpszClassName: class_name.as_ptr(),
        hIconSm: ptr::null_mut(),
    };

    user32::RegisterClassExW(&class);
    class_name
}

unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
                                   wparam: winapi::WPARAM, lparam: winapi::LPARAM)
                                   -> winapi::LRESULT
{
    user32::DefWindowProcW(window, msg, wparam, lparam)
}<commit_msg>Minor example change<commit_after>extern crate kernel32;
extern crate gdi32;
extern crate user32;
extern crate winapi;

#[macro_use]
extern crate vulkano;

use std::sync::Arc;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::mem;
use std::ptr;

fn main() {
    // The first step of any vulkan program is to create an instance.
    // TODO: for the moment the AMD driver crashes if you don't pass an ApplicationInfo, but in theory it's optional
    let app = vulkano::instance::ApplicationInfo { application_name: "test", application_version: 1, engine_name: "test", engine_version: 1 };
    let instance = vulkano::instance::Instance::new(Some(&app), &["VK_LAYER_LUNARG_draw_state"]).expect("failed to create instance");

    // We then choose which physical device to use.
    //
    // In a real application, there are three things to take into consideration:
    //
    // - Some devices support some optional features that may be required by your application.
    //   You should filter out the devices that don't support your app.
    //
    // - Not all devices can draw to a certain surface. Once you create your window, you have to
    //   choose a device that is capable of drawing to it.
    //
    // - You probably want to leave the choice between the remaining devices to the user.
    //
    // Here we are just going to use the first device.
    let physical = vulkano::instance::PhysicalDevice::enumerate(&instance)
                            .next().expect("no device available");
    println!("Using device: {} (type: {:?})", physical.name(), physical.ty());

    // The objective of this example is to draw a triangle on a window. To do so, we first have to
    // create the window in a platform-specific way. Then we create a `Surface` object from it.
    //
    // Surface objects are cross-platform. Once you have a `Surface` everything is the same again.
    let window = unsafe { create_window() };
    let surface = unsafe { vulkano::swapchain::Surface::from_hwnd(&instance, kernel32::GetModuleHandleW(ptr::null()), window).unwrap() };

    // The next step is to choose which queue will execute our draw commands.
    //
    // Devices can provide multiple queues to run things in parallel (for example a draw queue and
    // a compute queue). This is something you have to have to manage manually in Vulkan.
    //
    // We have to specify which queues you are going to use when we create the device, therefore
    // we need to choose that now.
    let queue = physical.queue_families().find(|q| q.supports_graphics() &&
                                                   surface.is_supported(q).unwrap_or(false))
                                                .expect("couldn't find a graphical queue family");

    // Now initializing the device.
    //
    // We have to pass a list of optional Vulkan features that must be enabled. TODO: explain this
    //
    // We also have to pass a list of queues to create and their priorities relative to each other.
    // Since we create one queue, we don't really care about the priority and just pass `0.5`.
    // The list of created queues is returned by the function alongside with the device.
    let (device, queues) = vulkano::device::Device::new(&physical, physical.supported_features(),
                                                        [(queue, 0.5)].iter().cloned(),
                                                        &["VK_LAYER_LUNARG_draw_state"])
                                                                .expect("failed to create device");

    // Since we can request multiple queues, the `queues` variable is a `Vec`. Our actual queue
    // is the first element.
    let queue = queues.into_iter().next().unwrap();

    // Before we can draw on the surface, we have to create what is called a swapchain. Creating
    // a swapchain allocates the color buffers that will contain the image that will ultimately
    // be visible on the screen. These images are returned alongside with the swapchain.
    let (swapchain, images) = {
        let caps = surface.get_capabilities(&physical).expect("failed to get surface capabilities");

        let dimensions = caps.current_extent.unwrap_or([1280, 1024]);
        let present = caps.present_modes[0];
        let usage = caps.supported_usage_flags;

        vulkano::swapchain::Swapchain::new(&device, &surface, 3,
                                           vulkano::formats::B8G8R8A8Srgb, dimensions, 1,
                                           &usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
                                           vulkano::swapchain::CompositeAlpha::Opaque,
                                           present, true).expect("failed to create swapchain")
    };

    // We now create a buffer that will store the shape of our triangle.
    //
    // The first parameter is the device to use, and the second parameter is how the buffer will
    // be used on the GPU side. This is a vertex buffer, and we need to tell this to the
    // implementation.
    //
    // The third parameter is where to get the memory where the buffer will be stored. It is very
    // important as it also determines the way you are going to access and modify your buffer.
    // Here we just ask for a basic host visible memory.
    //
    // Note that to store immutable data, the best way is to create two buffers. One buffer on
    // the CPU and one buffer on the GPU. We then write our data to the buffer on the CPU and
    // ask the GPU to copy it to the real buffer. This way the data is located on the most
    // efficient memory possible.
    let vertex_buffer: Arc<vulkano::buffer::Buffer<[Vertex; 3], _>> =
                                vulkano::buffer::Buffer::new(&device, &vulkano::buffer::Usage::all(),
                                                             vulkano::memory::HostVisible, &queue)
                                                                .expect("failed to create buffer");
    struct Vertex { position: [f32; 2] }
    impl_vertex!(Vertex, position);

    // The buffer that we created contains uninitialized data.
    // In order to fill it with data, we have to *map* it.
    {
        // The `try_write` function would return `None` if the buffer was in use by the GPU. This
        // obviously can't happen here, since we haven't ask the GPU to do anything yet.
        let mut mapping = vertex_buffer.try_write().unwrap();
        mapping[0].position = [-0.5, -0.25];
        mapping[1].position = [0.0, 0.5];
        mapping[2].position = [0.25, -0.1];
    }

    // The next step is to create the shaders.
    //
    // The shader creation API provided by the vulkano library is unsafe, for various reasons.
    //
    // Instead, in our build script we used the `vulkano-shaders` crate to parse our shaders at
    // compile time and provide a safe wrapper over vulkano's API. You can find the shaders'
    // source code in the `triangle_fs.glsl` and `triangle_vs.glsl` files.
    //
    // The code generated by the build script created a struct named `TriangleShader`, which we
    // can now use to load the shader.
    //
    // Because of some restrictions with the `include!` macro, we need to use a module.
    mod vs { include!{concat!(env!("OUT_DIR"), "/examples-triangle_vs.rs")} }
    let vs = vs::TriangleShader::load(&device).expect("failed to create shader module");
    mod fs { include!{concat!(env!("OUT_DIR"), "/examples-triangle_fs.rs")} }
    let fs = fs::TriangleShader::load(&device).expect("failed to create shader module");

    // At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL
    // implicitely does a lot of computation whenever you draw. In Vulkan, you have to do all this
    // manually.

    // We are going to create a command buffer below. Command buffers need to be allocated
    // from a *command buffer pool*, so we create the pool.
    let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.lock().unwrap().family())
                                                  .expect("failed to create command buffer pool");

    // We are going to draw on the images returned when creating the swapchain. To do so, we must
    // convert them into *image views*. TODO: explain more
    let images = images.into_iter().map(|image| {
        let image = image.transition(vulkano::image::Layout::PresentSrc, &cb_pool,
                                     &mut queue.lock().unwrap()).unwrap();
        vulkano::image::ImageView::new(&image).expect("failed to create image view")
    }).collect::<Vec<_>>();

    // The next step is to create a *renderpass*, which is an object that describes where the
    // output of the graphics pipeline will go. It describes the layout of the images
    // where the colors, depth and/or stencil information will be written.
    let renderpass = renderpass!{
        device: &device,
        attachments: {
            color [Clear]
        }
    }.unwrap();

    let pipeline: Arc<vulkano::pipeline::GraphicsPipeline<Arc<vulkano::buffer::Buffer<[Vertex; 3], _>>>> = {
        let ia = vulkano::pipeline::input_assembly::InputAssembly {
            topology: vulkano::pipeline::input_assembly::PrimitiveTopology::TriangleList,
            primitive_restart_enable: false,
        };

        let raster = Default::default();
        let ms = vulkano::pipeline::multisample::Multisample::disabled();
        let blend = vulkano::pipeline::blend::Blend {
            logic_op: None,
            blend_constants: Some([0.0; 4]),
        };

        let viewports = vulkano::pipeline::viewport::ViewportsState::Fixed {
            data: vec![(
                vulkano::pipeline::viewport::Viewport {
                    origin: [0.0, 0.0],
                    dimensions: [1244.0, 699.0],
                    depth_range: 0.0 .. 1.0
                },
                vulkano::pipeline::viewport::Scissor {
                    origin: [0, 0],
                    dimensions: [1244, 699],
                }
            )],
        };

        vulkano::pipeline::GraphicsPipeline::new(&device, &vs.main_entry_point(), &ia, &viewports,
                                                 &raster, &ms, &blend, &fs.main_entry_point(),
                                                 &renderpass.subpass(0).unwrap()).unwrap()
    };

    // The renderpass we created above only describes the layout of our framebuffers. We also need
    // to create the actual framebuffers.
    //
    // Since we need to draw to multiple images, we are going to create a different framebuffer for
    // each image.
    let framebuffers = images.iter().map(|image| {
        vulkano::framebuffer::Framebuffer::new(&renderpass, (1244, 699, 1), image).unwrap()
    }).collect::<Vec<_>>();

    // The final initialization step is to create a command buffer.
    //
    // A command buffer contains a list of commands that the GPU must execute. This can include
    // transfers between buffers, clearing images or attachments, etc. and draw commands. Here we
    // create a command buffer with a single command: drawing the triangle. The color attachment
    // is also cleared at the start.
    //
    // Since we have several images to draw on, we are also going to create one command buffer for
    // each image.
    let command_buffers = framebuffers.iter().map(|framebuffer| {
        vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
            .draw_inline(&renderpass, &framebuffer, [0.0, 0.0, 1.0, 1.0])
            .draw(&pipeline, vertex_buffer.clone(), &vulkano::command_buffer::DynamicState::none())
            .draw_end()
            .build().unwrap()
    }).collect::<Vec<_>>();

    // Initialization is finally finished!

    // Note that the only thing we need now are the `command_buffers` and `swapchain` variables.
    // Everything else is kept alive internally with `Arc`s (even the vertex buffer for example),
    // so the only variable that we need is this one.

    loop {
        // Before we can draw on the output, we have to *acquire* an image from the swapchain.
        // This operation returns the index of the image that we are allowed to draw upon..
        let image_num = swapchain.acquire_next_image().unwrap();

        // Our queue is wrapped around a `Mutex`, so we have to lock it.
        let mut queue = queue.lock().unwrap();

        // In order to draw, all we need to do is submit the command buffer to the queue.
        command_buffers[image_num].submit(&mut queue).unwrap();

        // The color output should now contain our triangle. But in order to show it on the
        // screen, we have to *present* the image. Depending on the presentation mode, this may
        // be shown immediatly or on the next redraw.
        swapchain.present(&mut queue, image_num).unwrap();

        // In a real application we want to submit things to the same queue in parallel, so we
        // shouldn't keep it locked too long.
        drop(queue);

        unsafe {
            let mut msg = mem::uninitialized();
            if user32::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) == 0 {
                break;
            }

            user32::TranslateMessage(&msg);
            user32::DispatchMessageW(&msg);
        }
    }
}

unsafe fn create_window() -> winapi::HWND {
    let class_name = register_window_class();

    let title: Vec<u16> = vec![b'V' as u16, b'u' as u16, b'l' as u16, b'k' as u16,
                               b'a' as u16, b'n' as u16, 0];

    user32::CreateWindowExW(winapi::WS_EX_APPWINDOW | winapi::WS_EX_WINDOWEDGE, class_name.as_ptr(),
                            title.as_ptr() as winapi::LPCWSTR,
                            winapi::WS_OVERLAPPEDWINDOW | winapi::WS_CLIPSIBLINGS |
                            winapi::WS_VISIBLE,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
                            ptr::null_mut(), ptr::null_mut(),
                            kernel32::GetModuleHandleW(ptr::null()),
                            ptr::null_mut())
}

unsafe fn register_window_class() -> Vec<u16> {
    let class_name: Vec<u16> = OsStr::new("Window Class").encode_wide().chain(Some(0).into_iter())
                                                         .collect::<Vec<u16>>();

    let class = winapi::WNDCLASSEXW {
        cbSize: mem::size_of::<winapi::WNDCLASSEXW>() as winapi::UINT,
        style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
        lpfnWndProc: Some(callback),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: kernel32::GetModuleHandleW(ptr::null()),
        hIcon: ptr::null_mut(),
        hCursor: ptr::null_mut(),
        hbrBackground: ptr::null_mut(),
        lpszMenuName: ptr::null(),
        lpszClassName: class_name.as_ptr(),
        hIconSm: ptr::null_mut(),
    };

    user32::RegisterClassExW(&class);
    class_name
}

unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
                                   wparam: winapi::WPARAM, lparam: winapi::LPARAM)
                                   -> winapi::LRESULT
{
    user32::DefWindowProcW(window, msg, wparam, lparam)
}<|endoftext|>


<commit_before>mod dsl_impls;
mod boxed;

pub use self::boxed::BoxedSelectStatement;

use backend::Backend;
use expression::*;
use query_source::*;
use result::QueryResult;
use super::distinct_clause::NoDistinctClause;
use super::group_by_clause::NoGroupByClause;
use super::limit_clause::NoLimitClause;
use super::offset_clause::NoOffsetClause;
use super::order_clause::NoOrderClause;
use super::select_clause::*;
use super::where_clause::NoWhereClause;
use super::{Query, QueryBuilder, QueryFragment, BuildQueryResult};

#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
#[must_use="Queries are only executed when calling `load`, `get_result` or similar."]
pub struct SelectStatement<
    From,
    Select = DefaultSelectClause,
    Distinct = NoDistinctClause,
    Where = NoWhereClause,
    Order = NoOrderClause,
    Limit = NoLimitClause,
    Offset = NoOffsetClause,
    GroupBy = NoGroupByClause,
> {
    select: Select,
    from: From,
    distinct: Distinct,
    where_clause: Where,
    order: Order,
    limit: Limit,
    offset: Offset,
    group_by: GroupBy,
}

impl<F, S, D, W, O, L, Of, G> SelectStatement<F, S, D, W, O, L, Of, G> {
    #[cfg_attr(feature = "clippy", allow(too_many_arguments))]
    pub fn new(
        select: S,
        from: F,
        distinct: D,
        where_clause: W,
        order: O,
        limit: L,
        offset: Of,
        group_by: G,
    ) -> Self {
        SelectStatement {
            select: select,
            from: from,
            distinct: distinct,
            where_clause: where_clause,
            order: order,
            limit: limit,
            offset: offset,
            group_by: group_by,
        }
    }
}

impl<F> SelectStatement<F> {
    pub fn simple(from: F) -> Self {
        SelectStatement::new(
            DefaultSelectClause,
            from,
            NoDistinctClause,
            NoWhereClause,
            NoOrderClause,
            NoLimitClause,
            NoOffsetClause,
            NoGroupByClause,
        )
    }
}

impl<F, S, D, W, O, L, Of, G> Query
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        S: SelectClauseExpression<F>,
{
    type SqlType = S::SelectClauseSqlType;
}

#[cfg(feature = "postgres")]
impl<F, S, D, W, O, L, Of, G> Expression
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        S: SelectClauseExpression<F>,
{
    type SqlType = ::types::Array<S::SelectClauseSqlType>;
}

#[cfg(not(feature = "postgres"))]
impl<F, S, D, W, O, L, Of, G> Expression
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        S: SelectClauseExpression<F>,
{
    type SqlType = S::SelectClauseSqlType;
}

impl<F, S, D, W, O, L, Of, G, DB> QueryFragment<DB>
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        DB: Backend,
        S: SelectClauseQueryFragment<F, DB>,
        F: QuerySource,
        F::FromClause: QueryFragment<DB>,
        D: QueryFragment<DB>,
        W: QueryFragment<DB>,
        O: QueryFragment<DB>,
        L: QueryFragment<DB>,
        Of: QueryFragment<DB>,
        G: QueryFragment<DB>,
{
    fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        out.push_sql("SELECT ");
        try!(self.distinct.to_sql(out));
        try!(self.select.to_sql(&self.from, out));
        out.push_sql(" FROM ");
        try!(self.from.from_clause().to_sql(out));
        try!(self.where_clause.to_sql(out));
        try!(self.group_by.to_sql(out));
        try!(self.order.to_sql(out));
        try!(self.limit.to_sql(out));
        try!(self.offset.to_sql(out));
        Ok(())
    }

    fn collect_binds(&self, out: &mut DB::BindCollector) -> QueryResult<()> {
        try!(self.distinct.collect_binds(out));
        try!(self.select.collect_binds(&self.from, out));
        try!(self.from.from_clause().collect_binds(out));
        try!(self.where_clause.collect_binds(out));
        try!(self.group_by.collect_binds(out));
        try!(self.order.collect_binds(out));
        try!(self.limit.collect_binds(out));
        try!(self.offset.collect_binds(out));
        Ok(())
    }

    fn is_safe_to_cache_prepared(&self) -> bool {
        self.distinct.is_safe_to_cache_prepared() &&
            self.select.is_safe_to_cache_prepared(&self.from) &&
            self.from.from_clause().is_safe_to_cache_prepared() &&
            self.where_clause.is_safe_to_cache_prepared() &&
            self.group_by.is_safe_to_cache_prepared() &&
            self.order.is_safe_to_cache_prepared() &&
            self.limit.is_safe_to_cache_prepared() &&
            self.offset.is_safe_to_cache_prepared()
    }
}

impl<S, D, W, O, L, Of, G, DB> QueryFragment<DB>
    for SelectStatement<(), S, D, W, O, L, Of, G> where
        DB: Backend,
        S: SelectClauseQueryFragment<(), DB>,
        D: QueryFragment<DB>,
        W: QueryFragment<DB>,
        O: QueryFragment<DB>,
        L: QueryFragment<DB>,
        Of: QueryFragment<DB>,
        G: QueryFragment<DB>,
{
    fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        out.push_sql("SELECT ");
        try!(self.distinct.to_sql(out));
        try!(self.select.to_sql(&(), out));
        try!(self.where_clause.to_sql(out));
        try!(self.group_by.to_sql(out));
        try!(self.order.to_sql(out));
        try!(self.limit.to_sql(out));
        try!(self.offset.to_sql(out));
        Ok(())
    }

    fn collect_binds(&self, out: &mut DB::BindCollector) -> QueryResult<()> {
        try!(self.distinct.collect_binds(out));
        try!(self.select.collect_binds(&(), out));
        try!(self.where_clause.collect_binds(out));
        try!(self.group_by.collect_binds(out));
        try!(self.order.collect_binds(out));
        try!(self.limit.collect_binds(out));
        try!(self.offset.collect_binds(out));
        Ok(())
    }

    fn is_safe_to_cache_prepared(&self) -> bool {
        self.distinct.is_safe_to_cache_prepared() &&
            self.select.is_safe_to_cache_prepared(&()) &&
            self.where_clause.is_safe_to_cache_prepared() &&
            self.group_by.is_safe_to_cache_prepared() &&
            self.order.is_safe_to_cache_prepared() &&
            self.limit.is_safe_to_cache_prepared() &&
            self.offset.is_safe_to_cache_prepared()
    }
}

impl_query_id!(SelectStatement<F, S, D, W, O, L, Of, G>);

impl<F, S, D, W, O, L, Of, G, QS> SelectableExpression<QS>
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        SelectStatement<F, S, D, W, O, L, Of, G>: AppearsOnTable<QS>,
{
}

impl<S, F, D, W, O, L, Of, G, QS> AppearsOnTable<QS>
    for SelectStatement<S, F, D, W, O, L, Of, G> where
        SelectStatement<S, F, D, W, O, L, Of, G>: Expression,
{
}

impl<F, S, D, W, O, L, Of, G> NonAggregate
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        SelectStatement<F, S, D, W, O, L, Of, G>: Expression,
{
}
<commit_msg>Document the common abbreviations in `select_statement`<commit_after>//! Within this module, types commonly use the following abbreviations:
//!
//! F: From Clause
//! S: Select Clause
//! D: Distinct Clause
//! W: Where Clause
//! O: Order By Clause
//! L: Limit Clause
//! Of: Offset Clause
//! G: Group By Clause
mod dsl_impls;
mod boxed;

pub use self::boxed::BoxedSelectStatement;

use backend::Backend;
use expression::*;
use query_source::*;
use result::QueryResult;
use super::distinct_clause::NoDistinctClause;
use super::group_by_clause::NoGroupByClause;
use super::limit_clause::NoLimitClause;
use super::offset_clause::NoOffsetClause;
use super::order_clause::NoOrderClause;
use super::select_clause::*;
use super::where_clause::NoWhereClause;
use super::{Query, QueryBuilder, QueryFragment, BuildQueryResult};

#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
#[must_use="Queries are only executed when calling `load`, `get_result` or similar."]
pub struct SelectStatement<
    From,
    Select = DefaultSelectClause,
    Distinct = NoDistinctClause,
    Where = NoWhereClause,
    Order = NoOrderClause,
    Limit = NoLimitClause,
    Offset = NoOffsetClause,
    GroupBy = NoGroupByClause,
> {
    select: Select,
    from: From,
    distinct: Distinct,
    where_clause: Where,
    order: Order,
    limit: Limit,
    offset: Offset,
    group_by: GroupBy,
}

impl<F, S, D, W, O, L, Of, G> SelectStatement<F, S, D, W, O, L, Of, G> {
    #[cfg_attr(feature = "clippy", allow(too_many_arguments))]
    pub fn new(
        select: S,
        from: F,
        distinct: D,
        where_clause: W,
        order: O,
        limit: L,
        offset: Of,
        group_by: G,
    ) -> Self {
        SelectStatement {
            select: select,
            from: from,
            distinct: distinct,
            where_clause: where_clause,
            order: order,
            limit: limit,
            offset: offset,
            group_by: group_by,
        }
    }
}

impl<F> SelectStatement<F> {
    pub fn simple(from: F) -> Self {
        SelectStatement::new(
            DefaultSelectClause,
            from,
            NoDistinctClause,
            NoWhereClause,
            NoOrderClause,
            NoLimitClause,
            NoOffsetClause,
            NoGroupByClause,
        )
    }
}

impl<F, S, D, W, O, L, Of, G> Query
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        S: SelectClauseExpression<F>,
{
    type SqlType = S::SelectClauseSqlType;
}

#[cfg(feature = "postgres")]
impl<F, S, D, W, O, L, Of, G> Expression
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        S: SelectClauseExpression<F>,
{
    type SqlType = ::types::Array<S::SelectClauseSqlType>;
}

#[cfg(not(feature = "postgres"))]
impl<F, S, D, W, O, L, Of, G> Expression
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        S: SelectClauseExpression<F>,
{
    type SqlType = S::SelectClauseSqlType;
}

impl<F, S, D, W, O, L, Of, G, DB> QueryFragment<DB>
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        DB: Backend,
        S: SelectClauseQueryFragment<F, DB>,
        F: QuerySource,
        F::FromClause: QueryFragment<DB>,
        D: QueryFragment<DB>,
        W: QueryFragment<DB>,
        O: QueryFragment<DB>,
        L: QueryFragment<DB>,
        Of: QueryFragment<DB>,
        G: QueryFragment<DB>,
{
    fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        out.push_sql("SELECT ");
        try!(self.distinct.to_sql(out));
        try!(self.select.to_sql(&self.from, out));
        out.push_sql(" FROM ");
        try!(self.from.from_clause().to_sql(out));
        try!(self.where_clause.to_sql(out));
        try!(self.group_by.to_sql(out));
        try!(self.order.to_sql(out));
        try!(self.limit.to_sql(out));
        try!(self.offset.to_sql(out));
        Ok(())
    }

    fn collect_binds(&self, out: &mut DB::BindCollector) -> QueryResult<()> {
        try!(self.distinct.collect_binds(out));
        try!(self.select.collect_binds(&self.from, out));
        try!(self.from.from_clause().collect_binds(out));
        try!(self.where_clause.collect_binds(out));
        try!(self.group_by.collect_binds(out));
        try!(self.order.collect_binds(out));
        try!(self.limit.collect_binds(out));
        try!(self.offset.collect_binds(out));
        Ok(())
    }

    fn is_safe_to_cache_prepared(&self) -> bool {
        self.distinct.is_safe_to_cache_prepared() &&
            self.select.is_safe_to_cache_prepared(&self.from) &&
            self.from.from_clause().is_safe_to_cache_prepared() &&
            self.where_clause.is_safe_to_cache_prepared() &&
            self.group_by.is_safe_to_cache_prepared() &&
            self.order.is_safe_to_cache_prepared() &&
            self.limit.is_safe_to_cache_prepared() &&
            self.offset.is_safe_to_cache_prepared()
    }
}

impl<S, D, W, O, L, Of, G, DB> QueryFragment<DB>
    for SelectStatement<(), S, D, W, O, L, Of, G> where
        DB: Backend,
        S: SelectClauseQueryFragment<(), DB>,
        D: QueryFragment<DB>,
        W: QueryFragment<DB>,
        O: QueryFragment<DB>,
        L: QueryFragment<DB>,
        Of: QueryFragment<DB>,
        G: QueryFragment<DB>,
{
    fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        out.push_sql("SELECT ");
        try!(self.distinct.to_sql(out));
        try!(self.select.to_sql(&(), out));
        try!(self.where_clause.to_sql(out));
        try!(self.group_by.to_sql(out));
        try!(self.order.to_sql(out));
        try!(self.limit.to_sql(out));
        try!(self.offset.to_sql(out));
        Ok(())
    }

    fn collect_binds(&self, out: &mut DB::BindCollector) -> QueryResult<()> {
        try!(self.distinct.collect_binds(out));
        try!(self.select.collect_binds(&(), out));
        try!(self.where_clause.collect_binds(out));
        try!(self.group_by.collect_binds(out));
        try!(self.order.collect_binds(out));
        try!(self.limit.collect_binds(out));
        try!(self.offset.collect_binds(out));
        Ok(())
    }

    fn is_safe_to_cache_prepared(&self) -> bool {
        self.distinct.is_safe_to_cache_prepared() &&
            self.select.is_safe_to_cache_prepared(&()) &&
            self.where_clause.is_safe_to_cache_prepared() &&
            self.group_by.is_safe_to_cache_prepared() &&
            self.order.is_safe_to_cache_prepared() &&
            self.limit.is_safe_to_cache_prepared() &&
            self.offset.is_safe_to_cache_prepared()
    }
}

impl_query_id!(SelectStatement<F, S, D, W, O, L, Of, G>);

impl<F, S, D, W, O, L, Of, G, QS> SelectableExpression<QS>
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        SelectStatement<F, S, D, W, O, L, Of, G>: AppearsOnTable<QS>,
{
}

impl<S, F, D, W, O, L, Of, G, QS> AppearsOnTable<QS>
    for SelectStatement<S, F, D, W, O, L, Of, G> where
        SelectStatement<S, F, D, W, O, L, Of, G>: Expression,
{
}

impl<F, S, D, W, O, L, Of, G> NonAggregate
    for SelectStatement<F, S, D, W, O, L, Of, G> where
        SelectStatement<F, S, D, W, O, L, Of, G>: Expression,
{
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use crate::{
    ast::ModuleName,
    env::{GlobalEnv, ModuleId},
    translate::{ModuleTranslator, Translator},
};
use anyhow::anyhow;
use codespan_reporting::diagnostic::{Diagnostic, Label};
use move_lang::{
    compiled_unit::{self, CompiledUnit},
    errors::Errors,
    expansion::ast::Program,
    move_compile_no_report, move_compile_to_expansion_no_report,
    parser::ast::FunctionName,
    shared::Address,
};

pub mod ast;
pub mod code_writer;
pub mod env;
pub mod symbol;
mod translate;
pub mod ty;

use crate::env::SCRIPT_MODULE_NAME;
#[allow(unused_imports)]
use log::{info, warn};
use move_ir_types::location::Spanned;
use move_lang::{
    expansion::ast::ModuleDefinition,
    parser::ast::{ModuleIdent, ModuleIdent_},
    shared::{unique_map::UniqueMap, Name},
};

// =================================================================================================
// Entry Point

pub fn run_spec_lang_compiler(
    targets: Vec<String>,
    deps: Vec<String>,
    address_opt: Option<&str>,
) -> anyhow::Result<GlobalEnv> {
    let address_opt = address_opt
        .map(Address::parse_str)
        .transpose()
        .map_err(|s| anyhow!(s))?;

    // Construct all sources from targets and deps, as we need bytecode for all of them.
    let mut all_sources = targets;
    all_sources.extend(deps.clone());
    let mut env = GlobalEnv::new();
    // First pass: compile move code.
    let (files, units_or_errors) = move_compile_no_report(&all_sources, &[], address_opt)?;
    // Enter sources into env, remember file ids as
    for (fname, fsrc) in files {
        env.add_source(fname, &fsrc, deps.contains(&fname.to_string()));
    }
    match units_or_errors {
        Err(errors) => {
            add_move_lang_errors(&mut env, errors);
        }
        Ok(units) => {
            let (verified_units, errors) = compiled_unit::verify_units(units);
            if !errors.is_empty() {
                add_move_lang_errors(&mut env, errors);
            } else {
                // Now compile again, up to expansion phase, to get hand on the expansion AST
                // which we merge with the verified units. This time we expect no errors.
                // The alternative to do a second parse and expansion pass is to make the expansion
                // AST clonable and tee it somehow out of the regular compile chain.
                let (_, eprog_or_errors) =
                    move_compile_to_expansion_no_report(&all_sources, &[], address_opt)?;
                let (eprog, comment_map) = eprog_or_errors.expect("no compilation errors");
                // Add any documentation comments found by the move compiler to the env.
                for (fname, documentation) in comment_map {
                    let file_id = env.get_file_id(fname).expect("file name defined");
                    env.add_documentation(file_id, documentation);
                }
                // Run the spec checker on verified units plus expanded AST. This will
                // populate the environment including any errors.
                run_spec_checker(&mut env, verified_units, eprog)?;
            }
        }
    };
    Ok(env)
}

fn add_move_lang_errors(env: &mut GlobalEnv, errors: Errors) {
    let mk_label = |env: &mut GlobalEnv, err: (move_ir_types::location::Loc, String)| {
        let loc = env.to_loc(&err.0);
        Label::new(loc.file_id(), loc.span(), err.1)
    };
    for mut error in errors {
        let primary = error.remove(0);
        let diag = Diagnostic::new_error("", mk_label(env, primary))
            .with_secondary_labels(error.into_iter().map(|e| mk_label(env, e)));
        env.add_diag(diag);
    }
}

#[allow(deprecated)]
fn run_spec_checker(
    env: &mut GlobalEnv,
    units: Vec<CompiledUnit>,
    mut eprog: Program,
) -> anyhow::Result<()> {
    let mut translator = Translator::new(env);
    // Merge the compiled units with the expanded program, preserving the order of the compiled
    // units which is topological w.r.t. use relation.
    let modules = units
        .into_iter()
        .flat_map(|unit| {
            Some(match unit {
                CompiledUnit::Module {
                    ident,
                    module,
                    source_map,
                    function_infos,
                } => {
                    let expanded_module = match eprog.modules.remove(&ident) {
                        Some(m) => m,
                        None => {
                            warn!(
                                "[internal] cannot associate bytecode module `{}` with AST",
                                ident
                            );
                            return None;
                        }
                    };
                    (ident, expanded_module, module, source_map, function_infos)
                }
                CompiledUnit::Script {
                    loc: _loc,
                    key,
                    script,
                    source_map,
                    function_info,
                } => {
                    let move_lang::expansion::ast::Script {
                        loc,
                        function_name,
                        constants,
                        function,
                        specs,
                    } = match eprog.scripts.remove(&key) {
                        Some(s) => s,
                        None => {
                            warn!(
                                "[internal] cannot associate bytecode script `{}` with AST",
                                key
                            );
                            return None;
                        }
                    };
                    // Convert the script into a module.
                    let ident = ModuleIdent(Spanned {
                        loc,
                        value: ModuleIdent_ {
                            name: move_lang::parser::ast::ModuleName(Name {
                                loc,
                                value: SCRIPT_MODULE_NAME.to_string(),
                            }),
                            address: Address::default(),
                        },
                    });
                    let mut function_infos = UniqueMap::new();
                    function_infos
                        .add(FunctionName(Name { loc, value: key }), function_info)
                        .unwrap();
                    // Construct a pseudo module definition.
                    let mut functions = UniqueMap::new();
                    functions.add(function_name.clone(), function).unwrap();
                    // As we now know the real function name and address, replace it in the
                    // data we got from bytecode.
                    let function_info = function_infos.into_iter().next().unwrap().1;
                    function_infos = UniqueMap::new();
                    function_infos.add(function_name, function_info).unwrap();
                    let expanded_module = ModuleDefinition {
                        loc,
                        is_source_module: true,
                        structs: UniqueMap::new(),
                        constants,
                        functions,
                        specs,
                    };
                    let module = script.into_module().1;
                    (ident, expanded_module, module, source_map, function_infos)
                }
            })
        })
        .enumerate();
    for (module_count, (module_id, expanded_module, compiled_module, source_map, function_infos)) in
        modules
    {
        let loc = translator.to_loc(&expanded_module.loc);
        let module_name = ModuleName::from_str(
            &module_id.0.value.address.to_string(),
            translator
                .env
                .symbol_pool()
                .make(&module_id.0.value.name.0.value),
        );
        let module_id = ModuleId::new(module_count);
        let mut module_translator = ModuleTranslator::new(&mut translator, module_id, module_name);
        module_translator.translate(
            loc,
            expanded_module,
            compiled_module,
            source_map,
            function_infos,
        );
    }
    Ok(())
}

// =================================================================================================
// Crate Helpers

/// Helper to project the 1st element from a vector of pairs.
pub(crate) fn project_1st<T: Clone, R>(v: &[(T, R)]) -> Vec<T> {
    v.iter().map(|(x, _)| x.clone()).collect()
}

/// Helper to project the 2nd element from a vector of pairs.
pub(crate) fn project_2nd<T, R: Clone>(v: &[(T, R)]) -> Vec<R> {
    v.iter().map(|(_, x)| x.clone()).collect()
}
<commit_msg>determinize iteration order over source files<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use crate::{
    ast::ModuleName,
    env::{GlobalEnv, ModuleId},
    translate::{ModuleTranslator, Translator},
};
use anyhow::anyhow;
use codespan_reporting::diagnostic::{Diagnostic, Label};
use move_lang::{
    compiled_unit::{self, CompiledUnit},
    errors::Errors,
    expansion::ast::Program,
    move_compile_no_report, move_compile_to_expansion_no_report,
    parser::ast::FunctionName,
    shared::Address,
};

pub mod ast;
pub mod code_writer;
pub mod env;
pub mod symbol;
mod translate;
pub mod ty;

use crate::env::SCRIPT_MODULE_NAME;
#[allow(unused_imports)]
use itertools::Itertools;
use log::warn;
use move_ir_types::location::Spanned;
use move_lang::{
    expansion::ast::ModuleDefinition,
    parser::ast::{ModuleIdent, ModuleIdent_},
    shared::{unique_map::UniqueMap, Name},
};

// =================================================================================================
// Entry Point

pub fn run_spec_lang_compiler(
    targets: Vec<String>,
    deps: Vec<String>,
    address_opt: Option<&str>,
) -> anyhow::Result<GlobalEnv> {
    let address_opt = address_opt
        .map(Address::parse_str)
        .transpose()
        .map_err(|s| anyhow!(s))?;

    // Construct all sources from targets and deps, as we need bytecode for all of them.
    let mut all_sources = targets;
    all_sources.extend(deps.clone());
    let mut env = GlobalEnv::new();
    // First pass: compile move code.
    let (files, units_or_errors) = move_compile_no_report(&all_sources, &[], address_opt)?;
    // Enter sources into env, remember file ids as
    for fname in files.keys().sorted() {
        let fsrc = &files[fname];
        env.add_source(fname, fsrc, deps.contains(&fname.to_string()));
    }
    match units_or_errors {
        Err(errors) => {
            add_move_lang_errors(&mut env, errors);
        }
        Ok(units) => {
            let (verified_units, errors) = compiled_unit::verify_units(units);
            if !errors.is_empty() {
                add_move_lang_errors(&mut env, errors);
            } else {
                // Now compile again, up to expansion phase, to get hand on the expansion AST
                // which we merge with the verified units. This time we expect no errors.
                // The alternative to do a second parse and expansion pass is to make the expansion
                // AST clonable and tee it somehow out of the regular compile chain.
                let (_, eprog_or_errors) =
                    move_compile_to_expansion_no_report(&all_sources, &[], address_opt)?;
                let (eprog, comment_map) = eprog_or_errors.expect("no compilation errors");
                // Add any documentation comments found by the move compiler to the env.
                for (fname, documentation) in comment_map {
                    let file_id = env.get_file_id(fname).expect("file name defined");
                    env.add_documentation(file_id, documentation);
                }
                // Run the spec checker on verified units plus expanded AST. This will
                // populate the environment including any errors.
                run_spec_checker(&mut env, verified_units, eprog)?;
            }
        }
    };
    Ok(env)
}

fn add_move_lang_errors(env: &mut GlobalEnv, errors: Errors) {
    let mk_label = |env: &mut GlobalEnv, err: (move_ir_types::location::Loc, String)| {
        let loc = env.to_loc(&err.0);
        Label::new(loc.file_id(), loc.span(), err.1)
    };
    for mut error in errors {
        let primary = error.remove(0);
        let diag = Diagnostic::new_error("", mk_label(env, primary))
            .with_secondary_labels(error.into_iter().map(|e| mk_label(env, e)));
        env.add_diag(diag);
    }
}

#[allow(deprecated)]
fn run_spec_checker(
    env: &mut GlobalEnv,
    units: Vec<CompiledUnit>,
    mut eprog: Program,
) -> anyhow::Result<()> {
    let mut translator = Translator::new(env);
    // Merge the compiled units with the expanded program, preserving the order of the compiled
    // units which is topological w.r.t. use relation.
    let modules = units
        .into_iter()
        .flat_map(|unit| {
            Some(match unit {
                CompiledUnit::Module {
                    ident,
                    module,
                    source_map,
                    function_infos,
                } => {
                    let expanded_module = match eprog.modules.remove(&ident) {
                        Some(m) => m,
                        None => {
                            warn!(
                                "[internal] cannot associate bytecode module `{}` with AST",
                                ident
                            );
                            return None;
                        }
                    };
                    (ident, expanded_module, module, source_map, function_infos)
                }
                CompiledUnit::Script {
                    loc: _loc,
                    key,
                    script,
                    source_map,
                    function_info,
                } => {
                    let move_lang::expansion::ast::Script {
                        loc,
                        function_name,
                        constants,
                        function,
                        specs,
                    } = match eprog.scripts.remove(&key) {
                        Some(s) => s,
                        None => {
                            warn!(
                                "[internal] cannot associate bytecode script `{}` with AST",
                                key
                            );
                            return None;
                        }
                    };
                    // Convert the script into a module.
                    let ident = ModuleIdent(Spanned {
                        loc,
                        value: ModuleIdent_ {
                            name: move_lang::parser::ast::ModuleName(Name {
                                loc,
                                value: SCRIPT_MODULE_NAME.to_string(),
                            }),
                            address: Address::default(),
                        },
                    });
                    let mut function_infos = UniqueMap::new();
                    function_infos
                        .add(FunctionName(Name { loc, value: key }), function_info)
                        .unwrap();
                    // Construct a pseudo module definition.
                    let mut functions = UniqueMap::new();
                    functions.add(function_name.clone(), function).unwrap();
                    // As we now know the real function name and address, replace it in the
                    // data we got from bytecode.
                    let function_info = function_infos.into_iter().next().unwrap().1;
                    function_infos = UniqueMap::new();
                    function_infos.add(function_name, function_info).unwrap();
                    let expanded_module = ModuleDefinition {
                        loc,
                        is_source_module: true,
                        structs: UniqueMap::new(),
                        constants,
                        functions,
                        specs,
                    };
                    let module = script.into_module().1;
                    (ident, expanded_module, module, source_map, function_infos)
                }
            })
        })
        .enumerate();
    for (module_count, (module_id, expanded_module, compiled_module, source_map, function_infos)) in
        modules
    {
        let loc = translator.to_loc(&expanded_module.loc);
        let module_name = ModuleName::from_str(
            &module_id.0.value.address.to_string(),
            translator
                .env
                .symbol_pool()
                .make(&module_id.0.value.name.0.value),
        );
        let module_id = ModuleId::new(module_count);
        let mut module_translator = ModuleTranslator::new(&mut translator, module_id, module_name);
        module_translator.translate(
            loc,
            expanded_module,
            compiled_module,
            source_map,
            function_infos,
        );
    }
    Ok(())
}

// =================================================================================================
// Crate Helpers

/// Helper to project the 1st element from a vector of pairs.
pub(crate) fn project_1st<T: Clone, R>(v: &[(T, R)]) -> Vec<T> {
    v.iter().map(|(x, _)| x.clone()).collect()
}

/// Helper to project the 2nd element from a vector of pairs.
pub(crate) fn project_2nd<T, R: Clone>(v: &[(T, R)]) -> Vec<R> {
    v.iter().map(|(_, x)| x.clone()).collect()
}
<|endoftext|>


<commit_before>//! Codec for chunk type 16 = FLI_COPY.

use std::io::Write;

use ::{FlicError,FlicResult,Raster,RasterMut};
use super::linscale;

/// Magic for a FLI_COPY chunk - No Compression.
///
/// This chunk contains an uncompressed image of the frame.  The
/// number of pixels following the chunk header is exactly the width
/// of the animation times the height of the animation.  The data
/// starts in the upper left corner with pixels copied from left to
/// right and then top to bottom.  This type of chunk is created when
/// the preferred compression method (SS2 or BRUN) generates more data
/// than the uncompressed frame image; a relatively rare situation.
pub const FLI_COPY: u16 = 16;

/// Magic for a FPS_COPY chunk - Postage Stamp, No Compression.
pub const FPS_COPY: u16 = FLI_COPY;

/// Decode a FLI_COPY chunk.
pub fn decode_fli_copy(src: &[u8], dst: &mut RasterMut)
        -> FlicResult<()> {
    if (dst.w <= 0) || (src.len() % dst.w != 0) {
        return Err(FlicError::WrongResolution);
    }

    let start = dst.stride * dst.y;
    let end = dst.stride * (dst.y + dst.h);
    let src_rows = src.chunks(dst.w);
    let dst_rows = dst.buf[start..end].chunks_mut(dst.stride);
    for (src_row, dst_row) in src_rows.zip(dst_rows) {
        let start = dst.x;
        let end = start + dst.w;
        dst_row[start..end].copy_from_slice(src_row);
    }

    Ok(())
}

/// Decode a FPS_COPY chunk.
pub fn decode_fps_copy(
        src: &[u8], src_w: usize, src_h: usize, dst: &mut RasterMut)
        -> FlicResult<()> {
    if src_w <= 0 || src_h <= 0 || (src_w * src_h > src.len()) {
        return Err(FlicError::WrongResolution);
    }

    for dy in 0..dst.h {
        let sy = linscale(src_h, dst.h, dy);
        let src_start = src_w * sy;
        let src_end = src_start + src_w;
        let dst_start = dst.stride * dy + dst.x;
        let dst_end = dst_start + dst.w;
        let src_row = &src[src_start..src_end];
        let dst_row = &mut dst.buf[dst_start..dst_end];

        for dx in 0..dst.w {
            let sx = linscale(src_w, dst.w, dx);
            dst_row[dx] = src_row[sx];
        }
    }

    Ok(())
}

/// Encode a FLI_COPY chunk.
pub fn encode_fli_copy<W: Write>(
        next: &Raster, w: &mut W)
        -> FlicResult<usize> {
    let start = next.stride * next.y;
    let end = next.stride * (next.y + next.h);
    for row in next.buf[start..end].chunks(next.stride) {
        let start = next.x;
        let end = start + next.w;
        try!(w.write_all(&row[start..end]));
    }

    Ok(next.w * next.h)
}
<commit_msg>Fix #3: FPS_COPY does not work with RasterMut with offset.<commit_after>//! Codec for chunk type 16 = FLI_COPY.

use std::io::Write;

use ::{FlicError,FlicResult,Raster,RasterMut};
use super::linscale;

/// Magic for a FLI_COPY chunk - No Compression.
///
/// This chunk contains an uncompressed image of the frame.  The
/// number of pixels following the chunk header is exactly the width
/// of the animation times the height of the animation.  The data
/// starts in the upper left corner with pixels copied from left to
/// right and then top to bottom.  This type of chunk is created when
/// the preferred compression method (SS2 or BRUN) generates more data
/// than the uncompressed frame image; a relatively rare situation.
pub const FLI_COPY: u16 = 16;

/// Magic for a FPS_COPY chunk - Postage Stamp, No Compression.
pub const FPS_COPY: u16 = FLI_COPY;

/// Decode a FLI_COPY chunk.
pub fn decode_fli_copy(src: &[u8], dst: &mut RasterMut)
        -> FlicResult<()> {
    if (dst.w <= 0) || (src.len() % dst.w != 0) {
        return Err(FlicError::WrongResolution);
    }

    let start = dst.stride * dst.y;
    let end = dst.stride * (dst.y + dst.h);
    let src_rows = src.chunks(dst.w);
    let dst_rows = dst.buf[start..end].chunks_mut(dst.stride);
    for (src_row, dst_row) in src_rows.zip(dst_rows) {
        let start = dst.x;
        let end = start + dst.w;
        dst_row[start..end].copy_from_slice(src_row);
    }

    Ok(())
}

/// Decode a FPS_COPY chunk.
pub fn decode_fps_copy(
        src: &[u8], src_w: usize, src_h: usize, dst: &mut RasterMut)
        -> FlicResult<()> {
    if src_w <= 0 || src_h <= 0 || (src_w * src_h > src.len()) {
        return Err(FlicError::WrongResolution);
    }

    for dy in 0..dst.h {
        let sy = linscale(src_h, dst.h, dy);
        let src_start = src_w * sy;
        let src_end = src_start + src_w;
        let dst_start = dst.stride * (dst.y + dy) + dst.x;
        let dst_end = dst_start + dst.w;
        let src_row = &src[src_start..src_end];
        let dst_row = &mut dst.buf[dst_start..dst_end];

        for dx in 0..dst.w {
            let sx = linscale(src_w, dst.w, dx);
            dst_row[dx] = src_row[sx];
        }
    }

    Ok(())
}

/// Encode a FLI_COPY chunk.
pub fn encode_fli_copy<W: Write>(
        next: &Raster, w: &mut W)
        -> FlicResult<usize> {
    let start = next.stride * next.y;
    let end = next.stride * (next.y + next.h);
    for row in next.buf[start..end].chunks(next.stride) {
        let start = next.x;
        let end = start + next.w;
        try!(w.write_all(&row[start..end]));
    }

    Ok(next.w * next.h)
}

#[cfg(test)]
mod tests {
    use ::RasterMut;
    use super::decode_fps_copy;

    #[test]
    fn test_decode_fps_copy() {
        let src = [
            11, 12, 13,
            21, 22, 23,
            31, 32, 33 ];

        let expected = [
            0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 11, 11, 12, 12, 13, 13,
            0, 0, 11, 11, 12, 12, 13, 13,
            0, 0, 21, 21, 22, 22, 23, 23,
            0, 0, 21, 21, 22, 22, 23, 23,
            0, 0, 31, 31, 32, 32, 33, 33,
            0, 0, 31, 31, 32, 32, 33, 33,
            0, 0, 0, 0, 0, 0, 0, 0 ];

        const SCREEN_W: usize = 8;
        const SCREEN_H: usize = 8;
        const NUM_COLS: usize = 256;
        let mut buf = [0; SCREEN_W * SCREEN_H];
        let mut pal = [0; 3 * NUM_COLS];
        let res = decode_fps_copy(&src, 3, 3,
                &mut RasterMut::with_offset(2, 1, 6, 6, SCREEN_W, &mut buf, &mut pal));
        assert!(res.is_ok());
        assert_eq!(&buf[..], &expected[..]);
    }
}
<|endoftext|>


<commit_before>#![crate_name = "rust-hl-lua-modules"]
#![feature(plugin_registrar)]
#![feature(quote)]

extern crate rustc;
extern crate syntax;

use syntax::ast;
use syntax::ast::Item;
use syntax::attr::AttrMetaMethods;
use syntax::codemap;
use syntax::ext::build::AstBuilder;
use syntax::ext::base;
use syntax::ext::quote::rt::ToSource;
use syntax::parse::token;
use syntax::ptr::P;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut ::rustc::plugin::Registry) {
    reg.register_syntax_extension(token::intern("export_lua_module"),
        base::Modifier(box expand_lua_module));
}

// handler for export_lua_module
pub fn expand_lua_module(ecx: &mut base::ExtCtxt, span: codemap::Span,
                        _: &ast::MetaItem, input_item: P<ast::Item>)
    -> P<ast::Item>
{
    let ecx: &base::ExtCtxt = &*ecx;

    // checking that the input item is a module
    // and creating the new item that will be returned by the function
    let (module, mut new_item) = match input_item.node {
        ast::ItemMod(ref module) => {
            (module, module.clone())
        },
        _ => {
            ecx.span_err(input_item.span,
                "`export_lua_module` extension is only allowed on modules");
            return ecx.item_mod(span.clone(), span.clone(), ecx.ident_of("dummy"), vec![],
                vec![], vec![]);
        }
    };

    // cleaning the content of `new_item`
    new_item.items.clear();

    // creating an array of the statements to add to the main Lua entry point
    let module_handler_body: Vec<P<ast::Stmt>> = {
        let mut module_handler_body = Vec::new();

        // iterating over elements inside the module
        for moditem in module.items.iter() {
            let moditem_name = moditem.ident.to_source();

            match moditem.node {
                ast::ItemFn(ref decl, ref style, ref abi, ref generics, ref block) => {
                    let moditem_name_slice = moditem_name.as_slice();
                    let moditem_name_item = ecx.ident_of(moditem_name_slice);

                    module_handler_body.push(
                        quote_stmt!(&*ecx,
                            table.set($moditem_name_slice.to_string(), $moditem_name_item);
                        )
                    );

                    new_item.items.push(ecx.item(
                        span.clone(),
                        moditem.ident.clone(),
                        moditem.attrs.clone(),
                        ast::ItemFn(
                            decl.clone(),
                            style.clone(),
                            abi.clone(),
                            generics.clone(),
                            ecx.block_expr(
                                quote_expr!(&*ecx,
                                    {
                                        let (tx, rx) = channel();
                                        native::start(0, core::ptr::null(), proc() {
                                            tx.send({
                                                $block
                                            })
                                        });
                                        rx.recv()
                                    }
                                )
                            )
                        )
                    ));
                },

                ast::ItemStatic(..) => {
                    let moditem_name_slice = moditem_name.as_slice();
                    let moditem_name_item = ecx.ident_of(moditem_name_slice);

                    module_handler_body.push(
                        quote_stmt!(&*ecx,
                            table.set($moditem_name_slice.to_string(), $moditem_name_item);
                        )
                    );

                    new_item.items.push(moditem.clone());
                },

                _ => {
                    ecx.span_warn(moditem.span,
                        format!("item `{}` is neiter a function nor a static
                            and will thus be ignored by `export_lua_module`",
                            moditem_name).as_slice());
                    new_item.items.push(moditem.clone());
                    continue;
                }
            };

            // handling lua_module_init
            if moditem.attrs.iter().find(|at| at.check_name("lua_module_init")).is_some() {
                let moditem_name_item = ecx.ident_of(moditem.ident.to_source().as_slice());
                module_handler_body.push(
                    quote_stmt!(ecx, $moditem_name_item())
                );
            }
        }

        module_handler_body
    };

    // adding extern crate declarations
    {
        let view_items = quote_item!(ecx,
            mod x {
                extern crate core;
                extern crate "rust-hl-lua" as lua;
                extern crate libc;
                extern crate native;
            }
        );

        let view_items = match view_items {
            Some(a) => a,
            None => {
                ecx.span_err(input_item.span,
                    "internal error in the library (could not parse view items)");
                return ecx.item_mod(span.clone(), span.clone(), ecx.ident_of("dummy"), vec![],
                    vec![], vec![]);
            }
        };

        // getting all the items
        let view_items = match view_items.node {
            ast::ItemMod(ref m) => m,
            _ => {
                ecx.span_err(span, "internal error in the library");
                return ecx.item_mod(span.clone(), span.clone(), ecx.ident_of("dummy"), vec![],
                    vec![], vec![]);
            }
        };

        for i in view_items.view_items.iter() {
            new_item.view_items.insert(0, i.clone())
        }
    }

    // generating the function that we will add inside the module
    {
        let function_body = {
            let mut function_body = Vec::new();

            function_body.push(quote_stmt!(ecx,
                let mut lua = self::lua::Lua::from_existing_state(lua, false);
            ));

            function_body.push(quote_stmt!(ecx,
                let mut table = lua.load_new_table();
            ));

            function_body.push_all_move(module_handler_body);

            function_body.push(quote_stmt!(ecx,
                ::std::mem::forget(table);
            ));

            ecx.block(span.clone(), function_body, Some(
                quote_expr!(ecx, 1)
            ))
        };

        // identifier for "luaopen_mylib"
        let luaopen_id = ecx.ident_of(format!("luaopen_{}", input_item.ident.to_source())
            .as_slice());

        // building the function itself
        let function = quote_item!(ecx,
            #[no_mangle]
            pub extern "C" fn $luaopen_id(lua: *mut self::libc::c_void)
                                                    -> self::libc::c_int {
                unsafe {
                    $function_body
               }
            }
        );

        let function = match function {
            Some(f) => f,
            None => {
                ecx.span_err(input_item.span,
                    "internal error in the library (could not parse function body)");
                return ecx.item_mod(span.clone(), span.clone(), ecx.ident_of("dummy"), vec![],
                    vec![], vec![]);
            }
        };

        // adding the function to the module
        new_item.items.push(function);
    }

    // returning
    ecx.item(
        span.clone(),
        input_item.ident.clone(),
        input_item.attrs.clone(),
        ast::ItemMod(new_item)
    ).map(|mut item| {
        item.vis = {
            if input_item.vis != ast::Public {
                ecx.span_warn(input_item.span,
                    "`export_lua_module` will turn the module into a public module");
            }
            ast::Public
        };
        item
    })
}
<commit_msg>Fix hl-modules too<commit_after>#![crate_name = "rust-hl-lua-modules"]
#![feature(plugin_registrar)]
#![feature(quote)]

extern crate rustc;
extern crate syntax;

use syntax::ast;
use syntax::ast::Item;
use syntax::attr::AttrMetaMethods;
use syntax::codemap;
use syntax::ext::build::AstBuilder;
use syntax::ext::base;
use syntax::ext::quote::rt::ToSource;
use syntax::parse::token;
use syntax::ptr::P;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut ::rustc::plugin::Registry) {
    reg.register_syntax_extension(token::intern("export_lua_module"),
        base::Modifier(box expand_lua_module));
}

// handler for export_lua_module
pub fn expand_lua_module(ecx: &mut base::ExtCtxt, span: codemap::Span,
                        _: &ast::MetaItem, input_item: P<ast::Item>)
    -> P<ast::Item>
{
    let ecx: &base::ExtCtxt = &*ecx;

    // checking that the input item is a module
    // and creating the new item that will be returned by the function
    let (module, mut new_item) = match input_item.node {
        ast::ItemMod(ref module) => {
            (module, module.clone())
        },
        _ => {
            ecx.span_err(input_item.span,
                "`export_lua_module` extension is only allowed on modules");
            return ecx.item_mod(span.clone(), span.clone(), ecx.ident_of("dummy"), vec![],
                vec![], vec![]);
        }
    };

    // cleaning the content of `new_item`
    new_item.items.clear();

    // creating an array of the statements to add to the main Lua entry point
    let module_handler_body: Vec<P<ast::Stmt>> = {
        let mut module_handler_body = Vec::new();

        // iterating over elements inside the module
        for moditem in module.items.iter() {
            let moditem_name = moditem.ident.to_source();

            match moditem.node {
                ast::ItemFn(ref decl, ref style, ref abi, ref generics, ref block) => {
                    let moditem_name_slice = moditem_name.as_slice();
                    let moditem_name_item = ecx.ident_of(moditem_name_slice);

                    module_handler_body.push(
                        quote_stmt!(&*ecx,
                            table.set($moditem_name_slice.to_string(), $moditem_name_item);
                        )
                    );

                    new_item.items.push(ecx.item(
                        span.clone(),
                        moditem.ident.clone(),
                        moditem.attrs.clone(),
                        ast::ItemFn(
                            decl.clone(),
                            style.clone(),
                            abi.clone(),
                            generics.clone(),
                            ecx.block_expr(
                                quote_expr!(&*ecx,
                                    {
                                        let (tx, rx) = channel();
                                        native::start(0, core::ptr::null(), proc() {
                                            tx.send({
                                                $block
                                            })
                                        });
                                        rx.recv()
                                    }
                                )
                            )
                        )
                    ));
                },

                ast::ItemStatic(..) => {
                    let moditem_name_slice = moditem_name.as_slice();
                    let moditem_name_item = ecx.ident_of(moditem_name_slice);

                    module_handler_body.push(
                        quote_stmt!(&*ecx,
                            table.set($moditem_name_slice.to_string(), $moditem_name_item);
                        )
                    );

                    new_item.items.push(moditem.clone());
                },

                _ => {
                    ecx.span_warn(moditem.span,
                        format!("item `{}` is neiter a function nor a static
                            and will thus be ignored by `export_lua_module`",
                            moditem_name).as_slice());
                    new_item.items.push(moditem.clone());
                    continue;
                }
            };

            // handling lua_module_init
            if moditem.attrs.iter().find(|at| at.check_name("lua_module_init")).is_some() {
                let moditem_name_item = ecx.ident_of(moditem.ident.to_source().as_slice());
                module_handler_body.push(
                    quote_stmt!(ecx, $moditem_name_item())
                );
            }
        }

        module_handler_body
    };

    // adding extern crate declarations
    {
        let view_items = quote_item!(ecx,
            mod x {
                extern crate core;
                extern crate "rust-hl-lua" as lua;
                extern crate libc;
                extern crate native;
            }
        );

        let view_items = match view_items {
            Some(a) => a,
            None => {
                ecx.span_err(input_item.span,
                    "internal error in the library (could not parse view items)");
                return ecx.item_mod(span.clone(), span.clone(), ecx.ident_of("dummy"), vec![],
                    vec![], vec![]);
            }
        };

        // getting all the items
        let view_items = match view_items.node {
            ast::ItemMod(ref m) => m,
            _ => {
                ecx.span_err(span, "internal error in the library");
                return ecx.item_mod(span.clone(), span.clone(), ecx.ident_of("dummy"), vec![],
                    vec![], vec![]);
            }
        };

        for i in view_items.view_items.iter() {
            new_item.view_items.insert(0, i.clone())
        }
    }

    // generating the function that we will add inside the module
    {
        let function_body = {
            let mut function_body = Vec::new();

            function_body.push(quote_stmt!(ecx,
                let mut lua = self::lua::Lua::from_existing_state(lua, false);
            ));

            function_body.push(quote_stmt!(ecx,
                let mut table = lua.load_new_table();
            ));

            function_body.extend(module_handler_body.into_iter());

            function_body.push(quote_stmt!(ecx,
                ::std::mem::forget(table);
            ));

            ecx.block(span.clone(), function_body, Some(
                quote_expr!(ecx, 1)
            ))
        };

        // identifier for "luaopen_mylib"
        let luaopen_id = ecx.ident_of(format!("luaopen_{}", input_item.ident.to_source())
            .as_slice());

        // building the function itself
        let function = quote_item!(ecx,
            #[no_mangle]
            pub extern "C" fn $luaopen_id(lua: *mut self::libc::c_void)
                                                    -> self::libc::c_int {
                unsafe {
                    $function_body
               }
            }
        );

        let function = match function {
            Some(f) => f,
            None => {
                ecx.span_err(input_item.span,
                    "internal error in the library (could not parse function body)");
                return ecx.item_mod(span.clone(), span.clone(), ecx.ident_of("dummy"), vec![],
                    vec![], vec![]);
            }
        };

        // adding the function to the module
        new_item.items.push(function);
    }

    // returning
    ecx.item(
        span.clone(),
        input_item.ident.clone(),
        input_item.attrs.clone(),
        ast::ItemMod(new_item)
    ).map(|mut item| {
        item.vis = {
            if input_item.vis != ast::Public {
                ecx.span_warn(input_item.span,
                    "`export_lua_module` will turn the module into a public module");
            }
            ast::Public
        };
        item
    })
}
<|endoftext|>


<commit_before>//! Targets the Nintendo Game Boy Advance (GBA),
//! a handheld game device from 2001.
//!
//! Please ping @Lokathor if changes are needed.
//!
//! The target profile assumes that you have the ARM binutils in your path (specifically the linker, `arm-none-eabi-ld`). They can be obtained for free for all major OSes from the ARM developer's website, and they may also be available in your system's package manager
//!
//! **Important:** This target profile **does not** specify a linker script or the ROM header. You'll still need to provide these yourself to construct a final  binary. Generally you'd do this with something like `-Clink-arg=-Tmy_script.ld` and `-Clink-arg=my_crt.o`.

use crate::spec::{LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        llvm_target: "thumbv4t-none-eabi".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "none".to_string(),
        target_env: "gba".to_string(),
        target_vendor: "nintendo".to_string(),
        arch: "arm".to_string(),
        /* Data layout args are '-' separated:
         * little endian
         * stack is 64-bit aligned (EABI)
         * pointers are 32-bit
         * i64 must be 64-bit aligned (EABI)
         * mangle names with ELF style
         * native integers are 32-bit
         * All other elements are default
         */
        data_layout: "e-S64-p:32:32-i64:64-m:e-n32".to_string(),
        linker_flavor: LinkerFlavor::Ld,
        options: TargetOptions {
            linker: Some("arm-none-eabi-ld".to_string()),
            linker_is_gnu: true,

            // extra args passed to the external assembler
            asm_args: vec!["-mcpu=arm7tdmi".to_string(), "-mthumb-interwork".to_string()],

            cpu: "arm7tdmi".to_string(),

            // minimum extra features, these cannot be disabled via -C
            features: "+soft-float,+strict-align".to_string(),

            executables: true,

            relocation_model: RelocModel::Static,

            //function_sections: bool,
            //exe_suffix: String,
            main_needs_argc_argv: false,

            // if we have thread-local storage
            has_elf_tls: false,

            // don't have atomic compare-and-swap
            atomic_cas: false,

            // always just abort
            panic_strategy: PanicStrategy::Abort,

            // ABIs to not use
            unsupported_abis: super::arm_base::unsupported_abis(),

            // The minimum alignment for global symbols.
            min_global_align: Some(4),

            // GBA has no builtins
            no_builtins: true,

            // this is off just like in the `thumb_base`
            emit_debug_gdb_scripts: false,

            ..TargetOptions::default()
        },
    })
}
<commit_msg>Resolve https://github.com/rust-lang/rust/pull/74419#discussion_r456142514<commit_after>//! Targets the Nintendo Game Boy Advance (GBA),
//! a handheld game device from 2001.
//!
//! Please ping @Lokathor if changes are needed.
//!
//! The target profile assumes that you have the ARM binutils in your path (specifically the linker, `arm-none-eabi-ld`). They can be obtained for free for all major OSes from the ARM developer's website, and they may also be available in your system's package manager
//!
//! **Important:** This target profile **does not** specify a linker script or the ROM header. You'll still need to provide these yourself to construct a final  binary. Generally you'd do this with something like `-Clink-arg=-Tmy_script.ld` and `-Clink-arg=my_crt.o`.

use crate::spec::{LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        llvm_target: "thumbv4t-none-eabi".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "none".to_string(),
        target_env: "gba".to_string(),
        target_vendor: "nintendo".to_string(),
        arch: "arm".to_string(),
        /* Data layout args are '-' separated:
         * little endian
         * stack is 64-bit aligned (EABI)
         * pointers are 32-bit
         * i64 must be 64-bit aligned (EABI)
         * mangle names with ELF style
         * native integers are 32-bit
         * All other elements are default
         */
        data_layout: "e-S64-p:32:32-i64:64-m:e-n32".to_string(),
        linker_flavor: LinkerFlavor::Ld,
        options: TargetOptions {
            linker: Some("arm-none-eabi-ld".to_string()),
            linker_is_gnu: true,

            // extra args passed to the external assembler
            asm_args: vec!["-mcpu=arm7tdmi".to_string(), "-mthumb-interwork".to_string()],

            cpu: "arm7tdmi".to_string(),

            // minimum extra features, these cannot be disabled via -C
            features: "+soft-float,+strict-align".to_string(),

            executables: true,

            relocation_model: RelocModel::Static,

            //function_sections: bool,
            //exe_suffix: String,
            main_needs_argc_argv: false,

            // if we have thread-local storage
            has_elf_tls: false,

            // don't have atomic compare-and-swap
            atomic_cas: false,

            // always just abort
            panic_strategy: PanicStrategy::Abort,

            // ABIs to not use
            unsupported_abis: super::arm_base::unsupported_abis(),

            // The minimum alignment for global symbols.
            min_global_align: Some(4),

            // this is off just like in the `thumb_base`
            emit_debug_gdb_scripts: false,

            ..TargetOptions::default()
        },
    })
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # Pipes
//!
//! Pipes should be familiar to anyone who has used a UNIX-like operating system before. They
//! connect the output of one component to the input of another. The tuple type `Pipe` is used
//! to represent the pipe between two components. For example:
//!
//! ```ignore
//! Pipe(first, second).into_component(consumer, publisher)
//! ```
//!

use super::super::tree::*;
use super::component::*;

///
/// Trait implemented by types that represent a pipe
///
pub trait ToPipe {
    ///
    /// The type of the output component
    ///
    type TOut: ConvertToComponent;

    ///
    /// Pipes a component into another component
    ///
    fn to_pipe(self) -> Self::TOut;
}

///
/// A component that takes the output of `TFirst` and connects it to the input of `TSecond`
///
pub struct Pipe<TFirst: ConvertToComponent, TSecond: ConvertToComponent>(TFirst, TSecond);

impl<TFirst: ConvertToComponent, TSecond: ConvertToComponent> ToPipe
for Pipe<TFirst, TSecond> {
    type TOut = Box<Fn(&TreeChange) -> TreeChange>;

    fn to_pipe(self) -> Self::TOut {
        unimplemented!()
    }
}

impl<TFirst: ConvertToComponent, TSecond: ConvertToComponent> ConvertToComponent
for Pipe<TFirst, TSecond> {
    #[inline]
    fn into_component(self, consumer: ConsumerRef, publisher: PublisherRef) -> ComponentRef {
        self.to_pipe().into_component(consumer, publisher)
    }
}

/*
 * TODO: would like to do this for function components as it's more efficient
 * but figuring out how to write the types so we don't get a conflict with the more generic version isn't easy
 *
 * use rustc_serialize::*;
impl<TIn: 'static + DecodeFromTreeNode, TResult: Decodable + Encodable + EncodeToTreeNode + 'static, TOut: 'static + ToTreeNode> ToPipe
for Pipe<Box<Fn(&TIn) -> TResult>, Box<Fn(&TResult) -> TOut>> {
    type TOut = Box<Fn(&TIn) -> TOut>;

    fn to_pipe(self) -> Self::TOut {
        Box::new(move |input| {
            let intermediate = self.0(input);
            self.1(&intermediate)
        })
    }
}
*/
<commit_msg>Remove the ToPipe trait and just use ConvertToComponent for pipes<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # Pipes
//!
//! Pipes should be familiar to anyone who has used a UNIX-like operating system before. They
//! connect the output of one component to the input of another. The tuple type `Pipe` is used
//! to represent the pipe between two components. For example:
//!
//! ```
//! # use tametree::component::*;
//! let add_one = component_fn(|x: &i32| { x+1 });
//! let add_two = component_fn(|x: &i32| { x+2 });
//!
//! let add_three = Pipe(add_one, add_two);
//! #
//! # let mut endpoint = ComponentEndPoint::<i32, i32>::new(add_three);
//! # endpoint.send(1);
//! # assert!(endpoint.recv().unwrap() == 4);
//! ```
//!
//! This pipe can be used as a component:
//!
//! ```
//! # use tametree::component::*;
//! # let add_one = component_fn(|x: &i32| { x+1 });
//! # let add_two = component_fn(|x: &i32| { x+2 });
//! #
//! # let add_three = Pipe(add_one, add_two);
//! #
//! let mut endpoint = ComponentEndPoint::<i32, i32>::new(add_three);
//! endpoint.send(1);
//! assert!(endpoint.recv().unwrap() == 4);
//! ```
//!
//!

use std::rc::*;

use super::component::*;
use super::immediate_publisher::*;

struct Pipeline(ComponentRef, ComponentRef);
impl Component for Pipeline { }
impl Drop for Pipeline { fn drop(&mut self) { } }

///
/// A component that takes the output of `TFirst` and connects it to the input of `TSecond`
///
pub struct Pipe<TFirst: ConvertToComponent, TSecond: ConvertToComponent>(pub TFirst, pub TSecond);

impl<TFirst: ConvertToComponent, TSecond: ConvertToComponent> ConvertToComponent
for Pipe<TFirst, TSecond> {
    #[inline]
    fn into_component(self, consumer: ConsumerRef, publisher: PublisherRef) -> ComponentRef {
        let Pipe(first, second) = self;
        let pipeline_start      = ImmediatePublisher::new();
        let pipeline_end        = pipeline_start.create_consumer();

        let first_component     = first.into_component(consumer, pipeline_start);
        let second_component    = second.into_component(pipeline_end, publisher);

        Rc::new(Pipeline(first_component, second_component))
    }
}

/*
 * TODO: would like to do this for function components as it's more efficient
 * but figuring out how to write the types so we don't get a conflict with the more generic version isn't easy
 *
 * use rustc_serialize::*;
impl<TIn: 'static + DecodeFromTreeNode, TResult: Decodable + Encodable + EncodeToTreeNode + 'static, TOut: 'static + ToTreeNode> ConvertToComponent
for Pipe<Box<Fn(&TIn) -> TResult>, Box<Fn(&TResult) -> TOut>> {
    ...
}
*/
<|endoftext|>


<commit_before>use std::fmt::{Display, Formatter, Error};

#[derive(Clone, Debug)]
pub enum StoreAction {
    Create,
    Retrieve,
    Update,
    Delete,
}

impl StoreAction {

    pub fn uppercase(&self) -> &str {
        match *self {
            StoreAction::Create   => "CREATE",
            StoreAction::Retrieve => "RETRIEVE",
            StoreAction::Update   => "UPDATE",
            StoreAction::Delete   => "DELETE",
        }
    }
}

impl Display for StoreAction {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        write!(fmt, "StoreAction: {}",
                match *self {
                    StoreAction::Create   => "create",
                    StoreAction::Retrieve => "retrieve",
                    StoreAction::Update   => "update",
                    StoreAction::Delete   => "delete",
                })
    }

}

<commit_msg>Add documentation for the StoreAction util type<commit_after>use std::fmt::{Display, Formatter, Error};

/// Utility type to specify which kind of store action is running
#[derive(Clone, Debug)]
pub enum StoreAction {
    Create,
    Retrieve,
    Update,
    Delete,
}

impl StoreAction {

    pub fn uppercase(&self) -> &str {
        match *self {
            StoreAction::Create   => "CREATE",
            StoreAction::Retrieve => "RETRIEVE",
            StoreAction::Update   => "UPDATE",
            StoreAction::Delete   => "DELETE",
        }
    }
}

impl Display for StoreAction {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        write!(fmt, "StoreAction: {}",
                match *self {
                    StoreAction::Create   => "create",
                    StoreAction::Retrieve => "retrieve",
                    StoreAction::Update   => "update",
                    StoreAction::Delete   => "delete",
                })
    }

}

<|endoftext|>