<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use compositing::resize_rate_limiter::ResizeRateLimiter;
use platform::{Application, Window};
use scripting::script_task::{LoadMsg, ScriptMsg};
use windowing::{ApplicationMethods, WindowMethods};

use azure::azure_hl::{BackendType, B8G8R8A8, DataSourceSurface, DrawTarget, SourceSurfaceMethods};
use core::cell::Cell;
use core::comm::{Chan, SharedChan, Port};
use core::util;
use geom::matrix::identity;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::compositor::{Compositor, LayerBuffer, LayerBufferSet};
use gfx::opts::Opts;
use layers::layers::{ARGB32Format, BasicImageData, ContainerLayer, ContainerLayerKind, Format};
use layers::layers::{Image, ImageData, ImageLayer, ImageLayerKind, RGB24Format, WithDataFn};
use layers::rendergl;
use layers::scene::Scene;
use servo_util::{time, url};
use servo_util::time::profile;
use servo_util::time::ProfilerChan;

mod resize_rate_limiter;

/// The implementation of the layers-based compositor.
#[deriving(Clone)]
pub struct CompositorImpl {
    chan: SharedChan<Msg>
}

impl CompositorImpl {
    /// Creates a new compositor instance.
    pub fn new(script_chan: SharedChan<ScriptMsg>,
               opts: Opts,
               prof_chan: ProfilerChan)
               -> CompositorImpl {
        let script_chan = Cell(script_chan);
        let chan: Chan<Msg> = do on_osmain |port| {
            debug!("preparing to enter main loop");
            run_main_loop(port, script_chan.take(), &opts, prof_chan.clone());
        };

        CompositorImpl {
            chan: SharedChan::new(chan)
        }
    }
}

/// Messages to the compositor.
pub enum Msg {
    BeginDrawing(Chan<LayerBufferSet>),
    Draw(Chan<LayerBufferSet>, LayerBufferSet),
    AddKeyHandler(Chan<()>),
    Exit
}

/// Azure surface wrapping to work with the layers infrastructure.
struct AzureDrawTargetImageData {
    draw_target: DrawTarget,
    data_source_surface: DataSourceSurface,
    size: Size2D<uint>
}

impl ImageData for AzureDrawTargetImageData {
    fn size(&self) -> Size2D<uint> {
        self.size
    }
    fn stride(&self) -> uint {
        self.data_source_surface.stride() as uint
    }
    fn format(&self) -> Format {
        // FIXME: This is not always correct. We should query the Azure draw target for the format.
        ARGB32Format
    }
    fn with_data(&self, f: WithDataFn) {
        do self.data_source_surface.with_data |data| {
            f(data);
        }
    }
}

fn run_main_loop(po: Port<Msg>, script_chan: SharedChan<ScriptMsg>, opts: &Opts, prof_chan:ProfilerChan) {
    let app: Application = ApplicationMethods::new();
    let window: @mut Window = WindowMethods::new(&app);
    let resize_rate_limiter = @mut ResizeRateLimiter(script_chan.clone());

    let surfaces = @mut SurfaceSet::new(opts.render_backend);
    let context = rendergl::init_render_context();

    // Create an initial layer tree.
    //
    // TODO: There should be no initial layer tree until the renderer creates one from the display
    // list. This is only here because we don't have that logic in the renderer yet.
    let root_layer = @mut ContainerLayer();
    let original_layer_transform;
    {
        let image_data = @BasicImageData::new(Size2D(0, 0), 0, RGB24Format, ~[]);
        let image = @mut Image::new(image_data as @ImageData);
        let image_layer = @mut ImageLayer(image);
        original_layer_transform = image_layer.common.transform;
        image_layer.common.set_transform(original_layer_transform.scale(800.0, 600.0, 1.0));
        root_layer.add_child(ImageLayerKind(image_layer));
    }

    let scene = @mut Scene(ContainerLayerKind(root_layer), Size2D(800.0, 600.0), identity());
    let key_handlers: @mut ~[Chan<()>] = @mut ~[];
    let done = @mut false;

    // FIXME: This should not be a separate offset applied after the fact but rather should be
    // applied to the layers themselves on a per-layer basis. However, this won't work until scroll
    // positions are sent to content.
    let world_offset = @mut Point2D(0f32, 0f32);

    let check_for_messages: @fn() = || {
        // Periodically check if the script task responded to our last resize event
        resize_rate_limiter.check_resize_response();

        // Handle messages
        while po.peek() {
            match po.recv() {
                AddKeyHandler(key_ch) => key_handlers.push(key_ch),
                BeginDrawing(sender) => surfaces.lend(sender),
                Exit => *done = true,

                Draw(sender, draw_target) => {
                    debug!("osmain: received new frame");

                    // Perform a buffer swap.
                    surfaces.put_back(draw_target);
                    surfaces.lend(sender);

                    // Iterate over the children of the container layer.
                    let mut current_layer_child = root_layer.first_child;

                    // Replace the image layer data with the buffer data.
                    let buffers = util::replace(&mut surfaces.front.layer_buffer_set.buffers, ~[]);
                    for buffers.each |buffer| {
                        let width = buffer.rect.size.width as uint;
                        let height = buffer.rect.size.height as uint;

                        debug!("osmain: compositing buffer rect %?", &buffer.rect);

                        let image_data = @AzureDrawTargetImageData {
                            draw_target: buffer.draw_target.clone(),
                            data_source_surface: buffer.draw_target.snapshot().get_data_surface(),
                            size: Size2D(width, height)
                        };
                        let image = @mut Image::new(image_data as @ImageData);

                        // Find or create an image layer.
                        let image_layer;
                        current_layer_child = match current_layer_child {
                            None => {
                                debug!("osmain: adding new image layer");
                                image_layer = @mut ImageLayer(image);
                                root_layer.add_child(ImageLayerKind(image_layer));
                                None
                            }
                            Some(ImageLayerKind(existing_image_layer)) => {
                                image_layer = existing_image_layer;
                                image_layer.set_image(image);

                                // Move on to the next sibling.
                                do current_layer_child.get().with_common |common| {
                                    common.next_sibling
                                }
                            }
                            Some(_) => fail!(~"found unexpected layer kind"),
                        };

                        // Set the layer's transform.
                        let mut origin = Point2D(buffer.rect.origin.x as f32,
                                                 buffer.rect.origin.y as f32);
                        let transform = original_layer_transform.translate(origin.x,
                                                                           origin.y,
                                                                           0.0);
                        let transform = transform.scale(width as f32, height as f32, 1.0);
                        image_layer.common.set_transform(transform)
                    }

                    surfaces.front.layer_buffer_set.buffers = buffers
                }
            }
        }
    };

    do window.set_composite_callback {
        do profile(time::CompositingCategory, prof_chan.clone()) {
            debug!("compositor: compositing");
            // Adjust the layer dimensions as necessary to correspond to the size of the window.
            scene.size = window.size();

            // Render the scene.
            rendergl::render_scene(context, scene);
        }

        window.present();
    }

    // Hook the windowing system's resize callback up to the resize rate limiter.
    do window.set_resize_callback |width, height| {
        debug!("osmain: window resized to %ux%u", width, height);
        resize_rate_limiter.window_resized(width, height);
    }

    // When the user enters a new URL, load it.
    do window.set_load_url_callback |url_string| {
        debug!("osmain: loading URL `%s`", url_string);
        script_chan.send(LoadMsg(url::make_url(url_string.to_str(), None)))
    }

    // When the user scrolls, move the layer around.
    do window.set_scroll_callback |delta| {
        // FIXME: Can't use `+=` due to a Rust bug.
        let world_offset_copy = *world_offset;
        *world_offset = world_offset_copy + delta;

        debug!("compositor: scrolled to %?", *world_offset);

        root_layer.common.set_transform(identity().translate(world_offset.x, world_offset.y, 0.0));

        window.set_needs_display()
    }

    // Enter the main event loop.
    while !*done {
        // Check for new messages coming from the rendering task.
        check_for_messages();

        // Check for messages coming from the windowing system.
        window.check_loop();
    }
}

/// Implementation of the abstract `Compositor` interface.
impl Compositor for CompositorImpl {
    fn begin_drawing(&self, next_dt: Chan<LayerBufferSet>) {
        self.chan.send(BeginDrawing(next_dt))
    }
    fn draw(&self, next_dt: Chan<LayerBufferSet>, draw_me: LayerBufferSet) {
        self.chan.send(Draw(next_dt, draw_me))
    }
}

struct SurfaceSet {
    front: Surface,
    back: Surface,
}

impl SurfaceSet {
    /// Creates a new surface set.
    fn new(backend: BackendType) -> SurfaceSet {
        SurfaceSet {
            front: Surface::new(backend),
            back: Surface::new(backend),
        }
    }

    fn lend(&mut self, receiver: Chan<LayerBufferSet>) {
        // We are in a position to lend out the surface?
        assert!(self.front.have);
        // Ok then take it
        let old_layer_buffers = util::replace(&mut self.front.layer_buffer_set.buffers, ~[]);
        let new_layer_buffers = do old_layer_buffers.map |layer_buffer| {
            let draw_target_ref = &layer_buffer.draw_target;
            let layer_buffer = LayerBuffer {
                draw_target: draw_target_ref.clone(),
                rect: copy layer_buffer.rect,
                stride: layer_buffer.stride
            };
            debug!("osmain: lending surface %?", layer_buffer);
            layer_buffer
        };
        self.front.layer_buffer_set.buffers = old_layer_buffers;

        let new_layer_buffer_set = LayerBufferSet { buffers: new_layer_buffers };
        receiver.send(new_layer_buffer_set);
        // Now we don't have it
        self.front.have = false;
        // But we (hopefully) have another!
        util::swap(&mut self.front, &mut self.back);
        // Let's look
        assert!(self.front.have);
    }

    fn put_back(&mut self, layer_buffer_set: LayerBufferSet) {
        // We have room for a return
        assert!(self.front.have);
        assert!(!self.back.have);

        self.back.layer_buffer_set = layer_buffer_set;

        // Now we have it again
        self.back.have = true;
    }
}

struct Surface {
    layer_buffer_set: LayerBufferSet,
    have: bool,
}

impl Surface {
    fn new(backend: BackendType) -> Surface {
        let layer_buffer = LayerBuffer {
            draw_target: DrawTarget::new(backend, Size2D(800, 600), B8G8R8A8),
            rect: Rect(Point2D(0u, 0u), Size2D(800u, 600u)),
            stride: 800 * 4
        };
        let layer_buffer_set = LayerBufferSet {
            buffers: ~[ layer_buffer ]
        };
        Surface {
            layer_buffer_set: layer_buffer_set,
            have: true
        }
    }
}

/// A function for spawning into the platform's main thread.
fn on_osmain<T: Owned>(f: ~fn(po: Port<T>)) -> Chan<T> {
    let (setup_po, setup_ch) = comm::stream();
    // FIXME: rust#6399
    let mut main_task = task::task();
    main_task.sched_mode(task::PlatformThread);
    do main_task.spawn {
        let (po, ch) = comm::stream();
        setup_ch.send(ch);
        f(po);
    }
    setup_po.recv()
}

<commit_msg>Remove unused 'mut'<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use compositing::resize_rate_limiter::ResizeRateLimiter;
use platform::{Application, Window};
use scripting::script_task::{LoadMsg, ScriptMsg};
use windowing::{ApplicationMethods, WindowMethods};

use azure::azure_hl::{BackendType, B8G8R8A8, DataSourceSurface, DrawTarget, SourceSurfaceMethods};
use core::cell::Cell;
use core::comm::{Chan, SharedChan, Port};
use core::util;
use geom::matrix::identity;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::compositor::{Compositor, LayerBuffer, LayerBufferSet};
use gfx::opts::Opts;
use layers::layers::{ARGB32Format, BasicImageData, ContainerLayer, ContainerLayerKind, Format};
use layers::layers::{Image, ImageData, ImageLayer, ImageLayerKind, RGB24Format, WithDataFn};
use layers::rendergl;
use layers::scene::Scene;
use servo_util::{time, url};
use servo_util::time::profile;
use servo_util::time::ProfilerChan;

mod resize_rate_limiter;

/// The implementation of the layers-based compositor.
#[deriving(Clone)]
pub struct CompositorImpl {
    chan: SharedChan<Msg>
}

impl CompositorImpl {
    /// Creates a new compositor instance.
    pub fn new(script_chan: SharedChan<ScriptMsg>,
               opts: Opts,
               prof_chan: ProfilerChan)
               -> CompositorImpl {
        let script_chan = Cell(script_chan);
        let chan: Chan<Msg> = do on_osmain |port| {
            debug!("preparing to enter main loop");
            run_main_loop(port, script_chan.take(), &opts, prof_chan.clone());
        };

        CompositorImpl {
            chan: SharedChan::new(chan)
        }
    }
}

/// Messages to the compositor.
pub enum Msg {
    BeginDrawing(Chan<LayerBufferSet>),
    Draw(Chan<LayerBufferSet>, LayerBufferSet),
    AddKeyHandler(Chan<()>),
    Exit
}

/// Azure surface wrapping to work with the layers infrastructure.
struct AzureDrawTargetImageData {
    draw_target: DrawTarget,
    data_source_surface: DataSourceSurface,
    size: Size2D<uint>
}

impl ImageData for AzureDrawTargetImageData {
    fn size(&self) -> Size2D<uint> {
        self.size
    }
    fn stride(&self) -> uint {
        self.data_source_surface.stride() as uint
    }
    fn format(&self) -> Format {
        // FIXME: This is not always correct. We should query the Azure draw target for the format.
        ARGB32Format
    }
    fn with_data(&self, f: WithDataFn) {
        do self.data_source_surface.with_data |data| {
            f(data);
        }
    }
}

fn run_main_loop(po: Port<Msg>, script_chan: SharedChan<ScriptMsg>, opts: &Opts, prof_chan:ProfilerChan) {
    let app: Application = ApplicationMethods::new();
    let window: @mut Window = WindowMethods::new(&app);
    let resize_rate_limiter = @mut ResizeRateLimiter(script_chan.clone());

    let surfaces = @mut SurfaceSet::new(opts.render_backend);
    let context = rendergl::init_render_context();

    // Create an initial layer tree.
    //
    // TODO: There should be no initial layer tree until the renderer creates one from the display
    // list. This is only here because we don't have that logic in the renderer yet.
    let root_layer = @mut ContainerLayer();
    let original_layer_transform;
    {
        let image_data = @BasicImageData::new(Size2D(0, 0), 0, RGB24Format, ~[]);
        let image = @mut Image::new(image_data as @ImageData);
        let image_layer = @mut ImageLayer(image);
        original_layer_transform = image_layer.common.transform;
        image_layer.common.set_transform(original_layer_transform.scale(800.0, 600.0, 1.0));
        root_layer.add_child(ImageLayerKind(image_layer));
    }

    let scene = @mut Scene(ContainerLayerKind(root_layer), Size2D(800.0, 600.0), identity());
    let key_handlers: @mut ~[Chan<()>] = @mut ~[];
    let done = @mut false;

    // FIXME: This should not be a separate offset applied after the fact but rather should be
    // applied to the layers themselves on a per-layer basis. However, this won't work until scroll
    // positions are sent to content.
    let world_offset = @mut Point2D(0f32, 0f32);

    let check_for_messages: @fn() = || {
        // Periodically check if the script task responded to our last resize event
        resize_rate_limiter.check_resize_response();

        // Handle messages
        while po.peek() {
            match po.recv() {
                AddKeyHandler(key_ch) => key_handlers.push(key_ch),
                BeginDrawing(sender) => surfaces.lend(sender),
                Exit => *done = true,

                Draw(sender, draw_target) => {
                    debug!("osmain: received new frame");

                    // Perform a buffer swap.
                    surfaces.put_back(draw_target);
                    surfaces.lend(sender);

                    // Iterate over the children of the container layer.
                    let mut current_layer_child = root_layer.first_child;

                    // Replace the image layer data with the buffer data.
                    let buffers = util::replace(&mut surfaces.front.layer_buffer_set.buffers, ~[]);
                    for buffers.each |buffer| {
                        let width = buffer.rect.size.width as uint;
                        let height = buffer.rect.size.height as uint;

                        debug!("osmain: compositing buffer rect %?", &buffer.rect);

                        let image_data = @AzureDrawTargetImageData {
                            draw_target: buffer.draw_target.clone(),
                            data_source_surface: buffer.draw_target.snapshot().get_data_surface(),
                            size: Size2D(width, height)
                        };
                        let image = @mut Image::new(image_data as @ImageData);

                        // Find or create an image layer.
                        let image_layer;
                        current_layer_child = match current_layer_child {
                            None => {
                                debug!("osmain: adding new image layer");
                                image_layer = @mut ImageLayer(image);
                                root_layer.add_child(ImageLayerKind(image_layer));
                                None
                            }
                            Some(ImageLayerKind(existing_image_layer)) => {
                                image_layer = existing_image_layer;
                                image_layer.set_image(image);

                                // Move on to the next sibling.
                                do current_layer_child.get().with_common |common| {
                                    common.next_sibling
                                }
                            }
                            Some(_) => fail!(~"found unexpected layer kind"),
                        };

                        // Set the layer's transform.
                        let origin = Point2D(buffer.rect.origin.x as f32,
                                             buffer.rect.origin.y as f32);
                        let transform = original_layer_transform.translate(origin.x,
                                                                           origin.y,
                                                                           0.0);
                        let transform = transform.scale(width as f32, height as f32, 1.0);
                        image_layer.common.set_transform(transform)
                    }

                    surfaces.front.layer_buffer_set.buffers = buffers
                }
            }
        }
    };

    do window.set_composite_callback {
        do profile(time::CompositingCategory, prof_chan.clone()) {
            debug!("compositor: compositing");
            // Adjust the layer dimensions as necessary to correspond to the size of the window.
            scene.size = window.size();

            // Render the scene.
            rendergl::render_scene(context, scene);
        }

        window.present();
    }

    // Hook the windowing system's resize callback up to the resize rate limiter.
    do window.set_resize_callback |width, height| {
        debug!("osmain: window resized to %ux%u", width, height);
        resize_rate_limiter.window_resized(width, height);
    }

    // When the user enters a new URL, load it.
    do window.set_load_url_callback |url_string| {
        debug!("osmain: loading URL `%s`", url_string);
        script_chan.send(LoadMsg(url::make_url(url_string.to_str(), None)))
    }

    // When the user scrolls, move the layer around.
    do window.set_scroll_callback |delta| {
        // FIXME: Can't use `+=` due to a Rust bug.
        let world_offset_copy = *world_offset;
        *world_offset = world_offset_copy + delta;

        debug!("compositor: scrolled to %?", *world_offset);

        root_layer.common.set_transform(identity().translate(world_offset.x, world_offset.y, 0.0));

        window.set_needs_display()
    }

    // Enter the main event loop.
    while !*done {
        // Check for new messages coming from the rendering task.
        check_for_messages();

        // Check for messages coming from the windowing system.
        window.check_loop();
    }
}

/// Implementation of the abstract `Compositor` interface.
impl Compositor for CompositorImpl {
    fn begin_drawing(&self, next_dt: Chan<LayerBufferSet>) {
        self.chan.send(BeginDrawing(next_dt))
    }
    fn draw(&self, next_dt: Chan<LayerBufferSet>, draw_me: LayerBufferSet) {
        self.chan.send(Draw(next_dt, draw_me))
    }
}

struct SurfaceSet {
    front: Surface,
    back: Surface,
}

impl SurfaceSet {
    /// Creates a new surface set.
    fn new(backend: BackendType) -> SurfaceSet {
        SurfaceSet {
            front: Surface::new(backend),
            back: Surface::new(backend),
        }
    }

    fn lend(&mut self, receiver: Chan<LayerBufferSet>) {
        // We are in a position to lend out the surface?
        assert!(self.front.have);
        // Ok then take it
        let old_layer_buffers = util::replace(&mut self.front.layer_buffer_set.buffers, ~[]);
        let new_layer_buffers = do old_layer_buffers.map |layer_buffer| {
            let draw_target_ref = &layer_buffer.draw_target;
            let layer_buffer = LayerBuffer {
                draw_target: draw_target_ref.clone(),
                rect: copy layer_buffer.rect,
                stride: layer_buffer.stride
            };
            debug!("osmain: lending surface %?", layer_buffer);
            layer_buffer
        };
        self.front.layer_buffer_set.buffers = old_layer_buffers;

        let new_layer_buffer_set = LayerBufferSet { buffers: new_layer_buffers };
        receiver.send(new_layer_buffer_set);
        // Now we don't have it
        self.front.have = false;
        // But we (hopefully) have another!
        util::swap(&mut self.front, &mut self.back);
        // Let's look
        assert!(self.front.have);
    }

    fn put_back(&mut self, layer_buffer_set: LayerBufferSet) {
        // We have room for a return
        assert!(self.front.have);
        assert!(!self.back.have);

        self.back.layer_buffer_set = layer_buffer_set;

        // Now we have it again
        self.back.have = true;
    }
}

struct Surface {
    layer_buffer_set: LayerBufferSet,
    have: bool,
}

impl Surface {
    fn new(backend: BackendType) -> Surface {
        let layer_buffer = LayerBuffer {
            draw_target: DrawTarget::new(backend, Size2D(800, 600), B8G8R8A8),
            rect: Rect(Point2D(0u, 0u), Size2D(800u, 600u)),
            stride: 800 * 4
        };
        let layer_buffer_set = LayerBufferSet {
            buffers: ~[ layer_buffer ]
        };
        Surface {
            layer_buffer_set: layer_buffer_set,
            have: true
        }
    }
}

/// A function for spawning into the platform's main thread.
fn on_osmain<T: Owned>(f: ~fn(po: Port<T>)) -> Chan<T> {
    let (setup_po, setup_ch) = comm::stream();
    // FIXME: rust#6399
    let mut main_task = task::task();
    main_task.sched_mode(task::PlatformThread);
    do main_task.spawn {
        let (po, ch) = comm::stream();
        setup_ch.send(ch);
        f(po);
    }
    setup_po.recv()
}

<|endoftext|>


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

#![allow(bad_style)]

pub struct Intrinsic {
    pub inputs: &'static [&'static Type],
    pub output: &'static Type,

    pub definition: IntrinsicDef,
}

#[derive(Clone, Hash, Eq, PartialEq)]
pub enum Type {
    Void,
    Integer(/* signed */ bool, u8, /* llvm width */ u8),
    Float(u8),
    Pointer(&'static Type, Option<&'static Type>, /* const */ bool),
    Vector(&'static Type, Option<&'static Type>, u16),
    Aggregate(bool, &'static [&'static Type]),
}

pub enum IntrinsicDef {
    Named(&'static str),
}

static I8: Type = Type::Integer(true, 8, 8);
static I16: Type = Type::Integer(true, 16, 16);
static I32: Type = Type::Integer(true, 32, 32);
static I64: Type = Type::Integer(true, 64, 64);
static U8: Type = Type::Integer(false, 8, 8);
static U16: Type = Type::Integer(false, 16, 16);
static U32: Type = Type::Integer(false, 32, 32);
static U64: Type = Type::Integer(false, 64, 64);
static F32: Type = Type::Float(32);
static F64: Type = Type::Float(64);

static I32_8: Type = Type::Integer(true, 32, 8);

static I8x8: Type = Type::Vector(&I8, None, 8);
static U8x8: Type = Type::Vector(&U8, None, 8);
static I8x16: Type = Type::Vector(&I8, None, 16);
static U8x16: Type = Type::Vector(&U8, None, 16);
static I8x32: Type = Type::Vector(&I8, None, 32);
static U8x32: Type = Type::Vector(&U8, None, 32);
static I8x64: Type = Type::Vector(&I8, None, 64);
static U8x64: Type = Type::Vector(&U8, None, 64);
static I8x128: Type = Type::Vector(&I8, None, 128);
static U8x128: Type = Type::Vector(&U8, None, 128);
static I8x256: Type = Type::Vector(&I8, None, 256);
static U8x256: Type = Type::Vector(&U8, None, 256);

static I16x4: Type = Type::Vector(&I16, None, 4);
static U16x4: Type = Type::Vector(&U16, None, 4);
static I16x8: Type = Type::Vector(&I16, None, 8);
static U16x8: Type = Type::Vector(&U16, None, 8);
static I16x16: Type = Type::Vector(&I16, None, 16);
static U16x16: Type = Type::Vector(&U16, None, 16);
static I16x32: Type = Type::Vector(&I16, None, 32);
static U16x32: Type = Type::Vector(&U16, None, 32);
static I16x64: Type = Type::Vector(&I16, None, 64);
static U16x64: Type = Type::Vector(&U16, None, 64);
static I16x128: Type = Type::Vector(&I16, None, 128);
static U16x128: Type = Type::Vector(&U16, None, 128);

static I32x2: Type = Type::Vector(&I32, None, 2);
static U32x2: Type = Type::Vector(&U32, None, 2);
static I32x4: Type = Type::Vector(&I32, None, 4);
static U32x4: Type = Type::Vector(&U32, None, 4);
static I32x8: Type = Type::Vector(&I32, None, 8);
static U32x8: Type = Type::Vector(&U32, None, 8);
static I32x16: Type = Type::Vector(&I32, None, 16);
static U32x16: Type = Type::Vector(&U32, None, 16);
static I32x32: Type = Type::Vector(&I32, None, 32);
static U32x32: Type = Type::Vector(&U32, None, 32);
static I32x64: Type = Type::Vector(&I32, None, 64);
static U32x64: Type = Type::Vector(&U32, None, 64);

static I64x1: Type = Type::Vector(&I64, None, 1);
static U64x1: Type = Type::Vector(&U64, None, 1);
static I64x2: Type = Type::Vector(&I64, None, 2);
static U64x2: Type = Type::Vector(&U64, None, 2);
static I64x4: Type = Type::Vector(&I64, None, 4);
static U64x4: Type = Type::Vector(&U64, None, 4);

static F32x2: Type = Type::Vector(&F32, None, 2);
static F32x4: Type = Type::Vector(&F32, None, 4);
static F32x8: Type = Type::Vector(&F32, None, 8);
static F64x1: Type = Type::Vector(&F64, None, 1);
static F64x2: Type = Type::Vector(&F64, None, 2);
static F64x4: Type = Type::Vector(&F64, None, 4);

static I32x4_F32: Type = Type::Vector(&I32, Some(&F32), 4);
static I32x8_F32: Type = Type::Vector(&I32, Some(&F32), 8);
static I64x2_F64: Type = Type::Vector(&I64, Some(&F64), 2);
static I64x4_F64: Type = Type::Vector(&I64, Some(&F64), 4);

static VOID: Type = Type::Void;

mod x86;
mod arm;
mod aarch64;
mod nvptx;
mod hexagon;
mod powerpc;

impl Intrinsic {
    pub fn find(name: &str) -> Option<Intrinsic> {
        if name.starts_with("x86_") {
            x86::find(name)
        } else if name.starts_with("arm_") {
            arm::find(name)
        } else if name.starts_with("aarch64_") {
            aarch64::find(name)
        } else if name.starts_with("nvptx_") {
            nvptx::find(name)
        } else if name.starts_with("Q6_") {
            hexagon::find(name)
        } else if name.starts_with("powerpc_") {
            powerpc::find(name)
        } else {
            None
        }
    }
}
<commit_msg>[nll] librustc_platform_intrinsics: enable feature(nll) for bootstrap<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(bad_style)]

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

pub struct Intrinsic {
    pub inputs: &'static [&'static Type],
    pub output: &'static Type,

    pub definition: IntrinsicDef,
}

#[derive(Clone, Hash, Eq, PartialEq)]
pub enum Type {
    Void,
    Integer(/* signed */ bool, u8, /* llvm width */ u8),
    Float(u8),
    Pointer(&'static Type, Option<&'static Type>, /* const */ bool),
    Vector(&'static Type, Option<&'static Type>, u16),
    Aggregate(bool, &'static [&'static Type]),
}

pub enum IntrinsicDef {
    Named(&'static str),
}

static I8: Type = Type::Integer(true, 8, 8);
static I16: Type = Type::Integer(true, 16, 16);
static I32: Type = Type::Integer(true, 32, 32);
static I64: Type = Type::Integer(true, 64, 64);
static U8: Type = Type::Integer(false, 8, 8);
static U16: Type = Type::Integer(false, 16, 16);
static U32: Type = Type::Integer(false, 32, 32);
static U64: Type = Type::Integer(false, 64, 64);
static F32: Type = Type::Float(32);
static F64: Type = Type::Float(64);

static I32_8: Type = Type::Integer(true, 32, 8);

static I8x8: Type = Type::Vector(&I8, None, 8);
static U8x8: Type = Type::Vector(&U8, None, 8);
static I8x16: Type = Type::Vector(&I8, None, 16);
static U8x16: Type = Type::Vector(&U8, None, 16);
static I8x32: Type = Type::Vector(&I8, None, 32);
static U8x32: Type = Type::Vector(&U8, None, 32);
static I8x64: Type = Type::Vector(&I8, None, 64);
static U8x64: Type = Type::Vector(&U8, None, 64);
static I8x128: Type = Type::Vector(&I8, None, 128);
static U8x128: Type = Type::Vector(&U8, None, 128);
static I8x256: Type = Type::Vector(&I8, None, 256);
static U8x256: Type = Type::Vector(&U8, None, 256);

static I16x4: Type = Type::Vector(&I16, None, 4);
static U16x4: Type = Type::Vector(&U16, None, 4);
static I16x8: Type = Type::Vector(&I16, None, 8);
static U16x8: Type = Type::Vector(&U16, None, 8);
static I16x16: Type = Type::Vector(&I16, None, 16);
static U16x16: Type = Type::Vector(&U16, None, 16);
static I16x32: Type = Type::Vector(&I16, None, 32);
static U16x32: Type = Type::Vector(&U16, None, 32);
static I16x64: Type = Type::Vector(&I16, None, 64);
static U16x64: Type = Type::Vector(&U16, None, 64);
static I16x128: Type = Type::Vector(&I16, None, 128);
static U16x128: Type = Type::Vector(&U16, None, 128);

static I32x2: Type = Type::Vector(&I32, None, 2);
static U32x2: Type = Type::Vector(&U32, None, 2);
static I32x4: Type = Type::Vector(&I32, None, 4);
static U32x4: Type = Type::Vector(&U32, None, 4);
static I32x8: Type = Type::Vector(&I32, None, 8);
static U32x8: Type = Type::Vector(&U32, None, 8);
static I32x16: Type = Type::Vector(&I32, None, 16);
static U32x16: Type = Type::Vector(&U32, None, 16);
static I32x32: Type = Type::Vector(&I32, None, 32);
static U32x32: Type = Type::Vector(&U32, None, 32);
static I32x64: Type = Type::Vector(&I32, None, 64);
static U32x64: Type = Type::Vector(&U32, None, 64);

static I64x1: Type = Type::Vector(&I64, None, 1);
static U64x1: Type = Type::Vector(&U64, None, 1);
static I64x2: Type = Type::Vector(&I64, None, 2);
static U64x2: Type = Type::Vector(&U64, None, 2);
static I64x4: Type = Type::Vector(&I64, None, 4);
static U64x4: Type = Type::Vector(&U64, None, 4);

static F32x2: Type = Type::Vector(&F32, None, 2);
static F32x4: Type = Type::Vector(&F32, None, 4);
static F32x8: Type = Type::Vector(&F32, None, 8);
static F64x1: Type = Type::Vector(&F64, None, 1);
static F64x2: Type = Type::Vector(&F64, None, 2);
static F64x4: Type = Type::Vector(&F64, None, 4);

static I32x4_F32: Type = Type::Vector(&I32, Some(&F32), 4);
static I32x8_F32: Type = Type::Vector(&I32, Some(&F32), 8);
static I64x2_F64: Type = Type::Vector(&I64, Some(&F64), 2);
static I64x4_F64: Type = Type::Vector(&I64, Some(&F64), 4);

static VOID: Type = Type::Void;

mod x86;
mod arm;
mod aarch64;
mod nvptx;
mod hexagon;
mod powerpc;

impl Intrinsic {
    pub fn find(name: &str) -> Option<Intrinsic> {
        if name.starts_with("x86_") {
            x86::find(name)
        } else if name.starts_with("arm_") {
            arm::find(name)
        } else if name.starts_with("aarch64_") {
            aarch64::find(name)
        } else if name.starts_with("nvptx_") {
            nvptx::find(name)
        } else if name.starts_with("Q6_") {
            hexagon::find(name)
        } else if name.starts_with("powerpc_") {
            powerpc::find(name)
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use resource_task::{ProgressMsg, Metadata, Payload, Done, LoaderTask, start_sending};

use std::io;
use std::io::File;
use servo_util::task::spawn_named;

//FIXME: https://github.com/mozilla/rust/issues/12892
static READ_SIZE: uint = 1;

fn read_all(reader: &mut io::Stream, progress_chan: &Sender<ProgressMsg>)
        -> Result<(), String> {
    loop {
        let mut buf = vec!();
        match reader.push_at_least(READ_SIZE, READ_SIZE, &mut buf) {
            Ok(_) => progress_chan.send(Payload(buf)),
            Err(e) => match e.kind {
                io::EndOfFile => return Ok(()),
                _ => return Err(e.desc.to_string()),
            }
        }
    }
}

pub fn factory() -> LoaderTask {
    let f: LoaderTask = proc(load_data, start_chan) {
        let url = load_data.url;
        assert!("file" == url.scheme.as_slice());
        let progress_chan = start_sending(start_chan, Metadata::default(url.clone()));
        spawn_named("file_loader", proc() {
            match File::open_mode(&Path::new(url.serialize_path().unwrap()), io::Open, io::Read) {
                Ok(ref mut reader) => {
                    let res = read_all(reader as &mut io::Stream, &progress_chan);
                    progress_chan.send(Done(res));
                }
                Err(e) => {
                    progress_chan.send(Done(Err(e.desc.to_string())));
                }
            };
        });
    };
    f
}
<commit_msg>Make perf_rainbow.html load ~20x faster by making the file loader read in 8 kB blocks.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use resource_task::{ProgressMsg, Metadata, Payload, Done, LoaderTask, start_sending};

use std::io;
use std::io::File;
use servo_util::task::spawn_named;

static READ_SIZE: uint = 8192;

fn read_all(reader: &mut io::Stream, progress_chan: &Sender<ProgressMsg>)
        -> Result<(), String> {
    loop {
        let mut buf = vec!();
        match reader.push_at_least(READ_SIZE, READ_SIZE, &mut buf) {
            Ok(_) => progress_chan.send(Payload(buf)),
            Err(e) => match e.kind {
                io::EndOfFile => {
                    if buf.len() > 0 {
                        progress_chan.send(Payload(buf));
                    }
                    return Ok(());
                }
                _ => return Err(e.desc.to_string()),
            }
        }
    }
}

pub fn factory() -> LoaderTask {
    let f: LoaderTask = proc(load_data, start_chan) {
        let url = load_data.url;
        assert!("file" == url.scheme.as_slice());
        let progress_chan = start_sending(start_chan, Metadata::default(url.clone()));
        spawn_named("file_loader", proc() {
            match File::open_mode(&Path::new(url.serialize_path().unwrap()), io::Open, io::Read) {
                Ok(ref mut reader) => {
                    let res = read_all(reader as &mut io::Stream, &progress_chan);
                    progress_chan.send(Done(res));
                }
                Err(e) => {
                    progress_chan.send(Done(Err(e.desc.to_string())));
                }
            };
        });
    };
    f
}
<|endoftext|>


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

#![crate_name = "foo"]

#![feature(optin_builtin_traits)]

pub struct Foo;

// @has foo/struct.Foo.html
// @!has - '//*[@class="synthetic-implementations"]' 'Auto Trait Implementations'
impl !Send for Foo {}
impl !Sync for Foo {}
<commit_msg>Fix empty-section.rs test<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_name = "foo"]

#![feature(optin_builtin_traits)]

pub struct Foo;

// @has foo/struct.Foo.html
// @!has - 'Auto Trait Implementations'
impl !Send for Foo {}
impl !Sync for Foo {}
<|endoftext|>


<commit_before><commit_msg>Add missing file<commit_after>use itertools::free::join;
use ast::{Expression, TreePrinter, Type, prefix};
use compileerror::{Span};

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct StructMember
{
    pub name: String,
    pub typ: Type,
    pub span: Span,
}

pub fn struct_member(name: &str, typ: Type, span: Span) -> StructMember
{
    StructMember{
        name: name.into(),
        typ: typ,
        span: span,
    }
}

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct StructDeclaration
{
    pub name: String,
    pub members: Vec<StructMember>,
    pub span: Span,
}

pub fn struct_declaration(name: &str, members: Vec<StructMember>, span: Span) -> StructDeclaration
{
    StructDeclaration{
        name: name.into(),
        members: members,
        span: span,
    }
}

impl StructDeclaration
{
    pub fn get_type(&self) -> Type
    {
        Type::Struct(self.name.clone(), self.members.iter().map(|m| m.typ.clone()).collect())
    }
}

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct StructInitializer
{
    pub struct_name: String,
    pub member_initializers: Vec<Expression>,
    pub span: Span,
}

pub fn struct_initializer(struct_name: &str, member_initializers: Vec<Expression>, span: Span) -> StructInitializer
{
    StructInitializer{
        struct_name: struct_name.into(),
        member_initializers: member_initializers,
        span: span,
    }
}

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct StructMemberAccess
{
    pub name: String,
    pub members: Vec<String>,
    pub span: Span,
}

pub fn struct_member_access(name: &str, members: Vec<String>, span: Span) -> StructMemberAccess
{
    StructMemberAccess{
        name: name.into(),
        members: members,
        span: span,
    }
}

impl TreePrinter for StructDeclaration
{
    fn print(&self, level: usize)
    {
        let p = prefix(level);
        println!("{}struct {} ({})", p, self.name, self.span);
        for m in &self.members {
            m.print(level + 1)
        }
    }
}

impl TreePrinter for StructInitializer
{
    fn print(&self, level: usize)
    {
        let p = prefix(level);
        println!("{}struct initializer {} ({})", p, self.struct_name, self.span);
        for m in &self.member_initializers {
            m.print(level + 1)
        }
    }
}

impl TreePrinter for StructMember
{
    fn print(&self, level: usize)
    {
        let p = prefix(level);
        println!("{}{}:{} ({})", p, self.name, self.typ, self.span);
    }
}

impl TreePrinter for StructMemberAccess
{
    fn print(&self, level: usize)
    {
        let p = prefix(level);
        println!("{}{}.{} ({})", p, self.name, join(self.members.iter(), "."), self.span);
    }
}
<|endoftext|>


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

/*!
 * Methods for the various MIR types. These are intended for use after
 * building is complete.
 */

use repr::*;
use rustc::middle::subst::Substs;
use rustc::middle::ty::{self, AdtDef, Ty};
use rustc_front::hir;

#[derive(Copy, Clone, Debug)]
pub enum LvalueTy<'tcx> {
    /// Normal type.
    Ty { ty: Ty<'tcx> },

    /// Downcast to a particular variant of an enum.
    Downcast { adt_def: AdtDef<'tcx>,
               substs: &'tcx Substs<'tcx>,
               variant_index: usize },
}

impl<'tcx> LvalueTy<'tcx> {
    pub fn from_ty(ty: Ty<'tcx>) -> LvalueTy<'tcx> {
        LvalueTy::Ty { ty: ty }
    }

    pub fn to_ty(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
        match *self {
            LvalueTy::Ty { ty } =>
                ty,
            LvalueTy::Downcast { adt_def, substs, variant_index: _ } =>
                tcx.mk_enum(adt_def, substs),
        }
    }

    pub fn projection_ty(self,
                         tcx: &ty::ctxt<'tcx>,
                         elem: &LvalueElem<'tcx>)
                         -> LvalueTy<'tcx>
    {
        match *elem {
            ProjectionElem::Deref =>
                LvalueTy::Ty {
                    ty: self.to_ty(tcx).builtin_deref(true, ty::LvaluePreference::NoPreference)
                                          .unwrap()
                                          .ty
                },
            ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
                LvalueTy::Ty {
                    ty: self.to_ty(tcx).builtin_index().unwrap()
                },
            ProjectionElem::Downcast(adt_def1, index) =>
                match self.to_ty(tcx).sty {
                    ty::TyEnum(adt_def, substs) => {
                        assert!(index < adt_def.variants.len());
                        assert_eq!(adt_def, adt_def1);
                        LvalueTy::Downcast { adt_def: adt_def,
                                             substs: substs,
                                             variant_index: index }
                    }
                    _ => {
                        tcx.sess.bug(&format!("cannot downcast non-enum type: `{:?}`", self))
                    }
                },
            ProjectionElem::Field(field) => {
                let field_ty = match self {
                    LvalueTy::Ty { ty } => match ty.sty {
                        ty::TyStruct(adt_def, substs) =>
                            adt_def.struct_variant().fields[field.index()].ty(tcx, substs),
                        ty::TyTuple(ref tys) =>
                            tys[field.index()],
                        _ =>
                            tcx.sess.bug(&format!("cannot get field of type: `{:?}`", ty)),
                    },
                    LvalueTy::Downcast { adt_def, substs, variant_index } =>
                        adt_def.variants[variant_index].fields[field.index()].ty(tcx, substs),
                };
                LvalueTy::Ty { ty: field_ty }
            }
        }
    }
}

impl<'tcx> Mir<'tcx> {
    pub fn operand_ty(&self,
                      tcx: &ty::ctxt<'tcx>,
                      operand: &Operand<'tcx>)
                      -> Ty<'tcx>
    {
        match *operand {
            Operand::Consume(ref l) => self.lvalue_ty(tcx, l).to_ty(tcx),
            Operand::Constant(ref c) => c.ty,
        }
    }

    pub fn binop_ty(&self,
                    tcx: &ty::ctxt<'tcx>,
                    op: BinOp,
                    lhs_ty: Ty<'tcx>,
                    rhs_ty: Ty<'tcx>)
                    -> Ty<'tcx>
    {
        // FIXME: handle SIMD correctly
        match op {
            BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div | BinOp::Rem |
            BinOp::BitXor | BinOp::BitAnd | BinOp::BitOr => {
                // these should be integers or floats of the same size.
                assert_eq!(lhs_ty, rhs_ty);
                lhs_ty
            }
            BinOp::Shl | BinOp::Shr => {
                lhs_ty // lhs_ty can be != rhs_ty
            }
            BinOp::Eq | BinOp::Lt | BinOp::Le |
            BinOp::Ne | BinOp::Ge | BinOp::Gt => {
                tcx.types.bool
            }
        }
    }

    pub fn lvalue_ty(&self,
                     tcx: &ty::ctxt<'tcx>,
                     lvalue: &Lvalue<'tcx>)
                     -> LvalueTy<'tcx>
    {
        match *lvalue {
            Lvalue::Var(index) =>
                LvalueTy::Ty { ty: self.var_decls[index as usize].ty },
            Lvalue::Temp(index) =>
                LvalueTy::Ty { ty: self.temp_decls[index as usize].ty },
            Lvalue::Arg(index) =>
                LvalueTy::Ty { ty: self.arg_decls[index as usize].ty },
            Lvalue::Static(def_id) =>
                LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty },
            Lvalue::ReturnPointer =>
                LvalueTy::Ty { ty: self.return_ty.unwrap() },
            Lvalue::Projection(ref proj) =>
                self.lvalue_ty(tcx, &proj.base).projection_ty(tcx, &proj.elem)
        }
    }
}

impl BorrowKind {
    pub fn to_mutbl_lossy(self) -> hir::Mutability {
        match self {
            BorrowKind::Mut => hir::MutMutable,
            BorrowKind::Shared => hir::MutImmutable,

            // We have no type corresponding to a unique imm borrow, so
            // use `&mut`. It gives all the capabilities of an `&uniq`
            // and hence is a safe "over approximation".
            BorrowKind::Unique => hir::MutMutable,
        }
    }
}

impl BinOp {
    pub fn to_hir_binop(self) -> hir::BinOp_ {
        match self {
            BinOp::Add => hir::BinOp_::BiAdd,
            BinOp::Sub => hir::BinOp_::BiSub,
            BinOp::Mul => hir::BinOp_::BiMul,
            BinOp::Div => hir::BinOp_::BiDiv,
            BinOp::Rem => hir::BinOp_::BiRem,
            BinOp::BitXor => hir::BinOp_::BiBitXor,
            BinOp::BitAnd => hir::BinOp_::BiBitAnd,
            BinOp::BitOr => hir::BinOp_::BiBitOr,
            BinOp::Shl => hir::BinOp_::BiShl,
            BinOp::Shr => hir::BinOp_::BiShr,
            BinOp::Eq => hir::BinOp_::BiEq,
            BinOp::Ne => hir::BinOp_::BiNe,
            BinOp::Lt => hir::BinOp_::BiLt,
            BinOp::Gt => hir::BinOp_::BiGt,
            BinOp::Le => hir::BinOp_::BiLe,
            BinOp::Ge => hir::BinOp_::BiGe
        }
    }
}
<commit_msg>Auto merge of #29817 - michaelwoerister:mir-ty-closure-fields, r=nikomatsakis<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * Methods for the various MIR types. These are intended for use after
 * building is complete.
 */

use repr::*;
use rustc::middle::subst::Substs;
use rustc::middle::ty::{self, AdtDef, Ty};
use rustc_front::hir;

#[derive(Copy, Clone, Debug)]
pub enum LvalueTy<'tcx> {
    /// Normal type.
    Ty { ty: Ty<'tcx> },

    /// Downcast to a particular variant of an enum.
    Downcast { adt_def: AdtDef<'tcx>,
               substs: &'tcx Substs<'tcx>,
               variant_index: usize },
}

impl<'tcx> LvalueTy<'tcx> {
    pub fn from_ty(ty: Ty<'tcx>) -> LvalueTy<'tcx> {
        LvalueTy::Ty { ty: ty }
    }

    pub fn to_ty(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
        match *self {
            LvalueTy::Ty { ty } =>
                ty,
            LvalueTy::Downcast { adt_def, substs, variant_index: _ } =>
                tcx.mk_enum(adt_def, substs),
        }
    }

    pub fn projection_ty(self,
                         tcx: &ty::ctxt<'tcx>,
                         elem: &LvalueElem<'tcx>)
                         -> LvalueTy<'tcx>
    {
        match *elem {
            ProjectionElem::Deref =>
                LvalueTy::Ty {
                    ty: self.to_ty(tcx).builtin_deref(true, ty::LvaluePreference::NoPreference)
                                          .unwrap()
                                          .ty
                },
            ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
                LvalueTy::Ty {
                    ty: self.to_ty(tcx).builtin_index().unwrap()
                },
            ProjectionElem::Downcast(adt_def1, index) =>
                match self.to_ty(tcx).sty {
                    ty::TyEnum(adt_def, substs) => {
                        assert!(index < adt_def.variants.len());
                        assert_eq!(adt_def, adt_def1);
                        LvalueTy::Downcast { adt_def: adt_def,
                                             substs: substs,
                                             variant_index: index }
                    }
                    _ => {
                        tcx.sess.bug(&format!("cannot downcast non-enum type: `{:?}`", self))
                    }
                },
            ProjectionElem::Field(field) => {
                let field_ty = match self {
                    LvalueTy::Ty { ty } => match ty.sty {
                        ty::TyStruct(adt_def, substs) =>
                            adt_def.struct_variant().fields[field.index()].ty(tcx, substs),
                        ty::TyTuple(ref tys) =>
                            tys[field.index()],
                        ty::TyClosure(_, ref closure_substs) =>
                            closure_substs.upvar_tys[field.index()],
                        _ =>
                            tcx.sess.bug(&format!("cannot get field of type: `{:?}`", ty)),
                    },
                    LvalueTy::Downcast { adt_def, substs, variant_index } =>
                        adt_def.variants[variant_index].fields[field.index()].ty(tcx, substs),
                };
                LvalueTy::Ty { ty: field_ty }
            }
        }
    }
}

impl<'tcx> Mir<'tcx> {
    pub fn operand_ty(&self,
                      tcx: &ty::ctxt<'tcx>,
                      operand: &Operand<'tcx>)
                      -> Ty<'tcx>
    {
        match *operand {
            Operand::Consume(ref l) => self.lvalue_ty(tcx, l).to_ty(tcx),
            Operand::Constant(ref c) => c.ty,
        }
    }

    pub fn binop_ty(&self,
                    tcx: &ty::ctxt<'tcx>,
                    op: BinOp,
                    lhs_ty: Ty<'tcx>,
                    rhs_ty: Ty<'tcx>)
                    -> Ty<'tcx>
    {
        // FIXME: handle SIMD correctly
        match op {
            BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div | BinOp::Rem |
            BinOp::BitXor | BinOp::BitAnd | BinOp::BitOr => {
                // these should be integers or floats of the same size.
                assert_eq!(lhs_ty, rhs_ty);
                lhs_ty
            }
            BinOp::Shl | BinOp::Shr => {
                lhs_ty // lhs_ty can be != rhs_ty
            }
            BinOp::Eq | BinOp::Lt | BinOp::Le |
            BinOp::Ne | BinOp::Ge | BinOp::Gt => {
                tcx.types.bool
            }
        }
    }

    pub fn lvalue_ty(&self,
                     tcx: &ty::ctxt<'tcx>,
                     lvalue: &Lvalue<'tcx>)
                     -> LvalueTy<'tcx>
    {
        match *lvalue {
            Lvalue::Var(index) =>
                LvalueTy::Ty { ty: self.var_decls[index as usize].ty },
            Lvalue::Temp(index) =>
                LvalueTy::Ty { ty: self.temp_decls[index as usize].ty },
            Lvalue::Arg(index) =>
                LvalueTy::Ty { ty: self.arg_decls[index as usize].ty },
            Lvalue::Static(def_id) =>
                LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty },
            Lvalue::ReturnPointer =>
                LvalueTy::Ty { ty: self.return_ty.unwrap() },
            Lvalue::Projection(ref proj) =>
                self.lvalue_ty(tcx, &proj.base).projection_ty(tcx, &proj.elem)
        }
    }
}

impl BorrowKind {
    pub fn to_mutbl_lossy(self) -> hir::Mutability {
        match self {
            BorrowKind::Mut => hir::MutMutable,
            BorrowKind::Shared => hir::MutImmutable,

            // We have no type corresponding to a unique imm borrow, so
            // use `&mut`. It gives all the capabilities of an `&uniq`
            // and hence is a safe "over approximation".
            BorrowKind::Unique => hir::MutMutable,
        }
    }
}

impl BinOp {
    pub fn to_hir_binop(self) -> hir::BinOp_ {
        match self {
            BinOp::Add => hir::BinOp_::BiAdd,
            BinOp::Sub => hir::BinOp_::BiSub,
            BinOp::Mul => hir::BinOp_::BiMul,
            BinOp::Div => hir::BinOp_::BiDiv,
            BinOp::Rem => hir::BinOp_::BiRem,
            BinOp::BitXor => hir::BinOp_::BiBitXor,
            BinOp::BitAnd => hir::BinOp_::BiBitAnd,
            BinOp::BitOr => hir::BinOp_::BiBitOr,
            BinOp::Shl => hir::BinOp_::BiShl,
            BinOp::Shr => hir::BinOp_::BiShr,
            BinOp::Eq => hir::BinOp_::BiEq,
            BinOp::Ne => hir::BinOp_::BiNe,
            BinOp::Lt => hir::BinOp_::BiLt,
            BinOp::Gt => hir::BinOp_::BiGt,
            BinOp::Le => hir::BinOp_::BiLe,
            BinOp::Ge => hir::BinOp_::BiGe
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>rust's reserved word and json<commit_after><|endoftext|>


<commit_before>
use std::iter::{repeat, Enumerate};
use std::slice;
use std::collections::VecMap;

use alphabets::Alphabet;

type LPS = Vec<usize>;

#[derive(Copy)]
pub struct KMP {
    m: usize
}

fn get_lps(pattern: &[u8]) -> LPS {
    let (m, mut q) = (pattern.len(), 0us);
    let mut lps: LPS = repeat(0).take(m).collect();
    for i in 1..m {
        while q > 0 && pattern[q] != pattern[i] {
            q = lps[q];
        }
        if pattern[q] == pattern[i] {
            q += 1;
        }
        lps[i] = q;
    }

    lps
}

struct Delta {
    table: Vec<VecMap<usize>>
}

impl Delta {
    fn new(pattern: &[u8], alphabet: Alphabet) -> Self {
        //assert!(alphabet.is_word(pattern));
        let k = alphabet.max_symbol()
            .expect("Expecting non-empty alphabet.") as usize + 1;
        let m = pattern.len();

        let mut init = VecMap::with_capacity(k);
        for c in alphabet.symbols.iter() {
            init.insert(c, 0);
        }
        *init.get_mut(&(pattern[0] as usize)).unwrap() = 1;

        let lps = get_lps(pattern);

        let mut table = Vec::with_capacity(m + 1);
        table.push(init);
        for q in 1..m+1 {
            let mut dq = VecMap::with_capacity(k);
            for c in alphabet.symbols.iter() {
                dq.insert(c, *table[lps[q - 1]].get(&c).unwrap());
            }
            if q < m {
                *dq.get_mut(&(pattern[q] as usize)).unwrap() = q;
            }
            table.push(dq);
        }

        Delta { table: table }
    }
}

pub struct FindAll<'a> {
    kmp: KMP,
    q: usize,
    text: Enumerate<slice::Iter<'a, u8>>
}

impl<'a> Iterator for FindAll<'a> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        for (i, &c) in self.text {
            // TODO self.q = self.kmp.delta(self.q, c);
            if self.q == self.kmp.m {
                return Some(i - self.kmp.m + 1);
            }
        }

        None
    }
}

#[cfg(test)]
mod tests {
    use super::{get_lps, Delta};
    use alphabets::Alphabet;

    #[test]
    fn test_get_lps() {
        let pattern = b"ababaca";
        let lps = get_lps(pattern);
        assert_eq!(lps, [0, 0, 1, 2, 3, 0, 1]);
    }

    #[test]
    fn test_delta() {
        let pattern = b"ababaca";
        let alphabet = Alphabet::new(pattern);
        let delta = Delta::new(pattern, alphabet);

    }
}
<commit_msg>Failing test.<commit_after>
use std::iter::{repeat, Enumerate};
use std::slice;
use std::collections::VecMap;

use alphabets::Alphabet;

type LPS = Vec<usize>;

#[derive(Copy)]
pub struct KMP {
    m: usize
}

fn get_lps(pattern: &[u8]) -> LPS {
    let (m, mut q) = (pattern.len(), 0us);
    let mut lps: LPS = repeat(0).take(m).collect();
    for i in 1..m {
        while q > 0 && pattern[q] != pattern[i] {
            q = lps[q];
        }
        if pattern[q] == pattern[i] {
            q += 1;
        }
        lps[i] = q;
    }

    lps
}

struct Delta {
    table: Vec<VecMap<usize>>
}

impl Delta {
    fn new(pattern: &[u8], alphabet: Alphabet) -> Self {
        //assert!(alphabet.is_word(pattern));
        let k = alphabet.max_symbol()
            .expect("Expecting non-empty alphabet.") as usize + 1;
        let m = pattern.len();

        let mut init = VecMap::with_capacity(k);
        for c in alphabet.symbols.iter() {
            init.insert(c, 0);
        }
        *init.get_mut(&(pattern[0] as usize)).unwrap() = 1;

        let lps = get_lps(pattern);

        let mut table = Vec::with_capacity(m + 1);
        table.push(init);
        for q in 1..m+1 {
            let mut dq = VecMap::with_capacity(k);
            for c in alphabet.symbols.iter() {
                dq.insert(c, *table[lps[q - 1]].get(&c).unwrap());
            }
            if q < m {
                *dq.get_mut(&(pattern[q] as usize)).unwrap() = q;
            }
            table.push(dq);
        }

        Delta { table: table }
    }

    fn get(&self, q: usize, a: u8) -> usize {
        *self.table[q].get(&(a as usize)).expect("Missing symbol in alphabet (is the text a word of the given alphabet?)")
    }
}

pub struct FindAll<'a> {
    kmp: KMP,
    q: usize,
    text: Enumerate<slice::Iter<'a, u8>>
}

impl<'a> Iterator for FindAll<'a> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        for (i, &c) in self.text {
            // TODO self.q = self.kmp.delta(self.q, c);
            if self.q == self.kmp.m {
                return Some(i - self.kmp.m + 1);
            }
        }

        None
    }
}

#[cfg(test)]
mod tests {
    use super::{get_lps, Delta};
    use alphabets::Alphabet;

    #[test]
    fn test_get_lps() {
        let pattern = b"ababaca";
        let lps = get_lps(pattern);
        assert_eq!(lps, [0, 0, 1, 2, 3, 0, 1]);
    }

    #[test]
    fn test_delta() {
        let pattern = b"abbab";
        let alphabet = Alphabet::new(pattern);
        let delta = Delta::new(pattern, alphabet);
        assert_eq!(delta.get(0, b'a'), 1);
        assert_eq!(delta.get(0, b'b'), 0);
        assert_eq!(delta.get(1, b'a'), 1);
        assert_eq!(delta.get(1, b'b'), 2);
        assert_eq!(delta.get(2, b'a'), 1);
        assert_eq!(delta.get(2, b'b'), 3);
        assert_eq!(delta.get(3, b'a'), 4);
        assert_eq!(delta.get(3, b'b'), 0);
        assert_eq!(delta.get(4, b'a'), 1);
        assert_eq!(delta.get(4, b'b'), 5);
        assert_eq!(delta.get(5, b'a'), 1);
        assert_eq!(delta.get(5, b'b'), 3);
    }
}
<|endoftext|>


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

use std::env;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Write;

struct Test {
    repo: &'static str,
    name: &'static str,
    sha: &'static str,
    lock: Option<&'static str>,
}

const TEST_REPOS: &'static [Test] = &[
    Test {
        name: "cargo",
        repo: "https://github.com/rust-lang/cargo",
        sha: "26288f799427f9cc6e8bdddd782a17a8156ebc64",
        lock: None,
    },
    Test {
        name: "iron",
        repo: "https://github.com/iron/iron",
        sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
        lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
    },
];

fn main() {
    let args = env::args().collect::<Vec<_>>();
    let ref cargo = args[1];
    let out_dir = Path::new(&args[2]);
    let ref cargo = Path::new(cargo);

    for test in TEST_REPOS.iter().rev() {
        test_repo(cargo, out_dir, test);
    }
}

fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) {
    println!("testing {}", test.repo);
    let dir = clone_repo(test, out_dir);
    if let Some(lockfile) = test.lock {
        File::create(&dir.join("Cargo.lock")).expect("")
            .write_all(lockfile.as_bytes()).expect("");
    }
    if !run_cargo_test(cargo, &dir) {
        panic!("tests failed for {}", test.repo);
    }
}

fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
    let out_dir = out_dir.join(test.name);

    if !out_dir.join(".git").is_dir() {
        let status = Command::new("git")
            .arg("init")
            .arg(&out_dir)
            .status()
            .expect("");
        assert!(status.success());
    }

    // Try progressively deeper fetch depths to find the commit
    let mut found = false;
    for depth in &[0, 1, 10, 100, 1000, 100000] {
        if *depth > 0 {
            let status = Command::new("git")
                .arg("fetch")
                .arg(test.repo)
                .arg("master")
                .arg(&format!("--depth={}", depth))
                .current_dir(&out_dir)
                .status()
                .expect("");
            assert!(status.success());
        }

        let status = Command::new("git")
            .arg("reset")
            .arg(test.sha)
            .arg("--hard")
            .current_dir(&out_dir)
            .status()
            .expect("");

        if status.success() {
            found = true;
            break;
        }
    }

    if !found {
        panic!("unable to find commit {}", test.sha)
    }
    let status = Command::new("git")
        .arg("clean")
        .arg("-fdx")
        .current_dir(&out_dir)
        .status()
        .unwrap();
    assert!(status.success());

    out_dir
}

fn run_cargo_test(cargo_path: &Path, crate_path: &Path) -> bool {
    let status = Command::new(cargo_path)
        .arg("test")
        // Disable rust-lang/cargo's cross-compile tests
        .env("CFG_DISABLE_CROSS_TESTS", "1")
        .current_dir(crate_path)
        .status()
        .expect("");

    status.success()
}
<commit_msg>Update cargo version in cargotest<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::env;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Write;

struct Test {
    repo: &'static str,
    name: &'static str,
    sha: &'static str,
    lock: Option<&'static str>,
}

const TEST_REPOS: &'static [Test] = &[
    Test {
        name: "cargo",
        repo: "https://github.com/rust-lang/cargo",
        sha: "7d79da08238e3d47e0bc4406155bdcc45ccb8c82",
        lock: None,
    },
    Test {
        name: "iron",
        repo: "https://github.com/iron/iron",
        sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
        lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
    },
];

fn main() {
    let args = env::args().collect::<Vec<_>>();
    let ref cargo = args[1];
    let out_dir = Path::new(&args[2]);
    let ref cargo = Path::new(cargo);

    for test in TEST_REPOS.iter().rev() {
        test_repo(cargo, out_dir, test);
    }
}

fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) {
    println!("testing {}", test.repo);
    let dir = clone_repo(test, out_dir);
    if let Some(lockfile) = test.lock {
        File::create(&dir.join("Cargo.lock")).expect("")
            .write_all(lockfile.as_bytes()).expect("");
    }
    if !run_cargo_test(cargo, &dir) {
        panic!("tests failed for {}", test.repo);
    }
}

fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
    let out_dir = out_dir.join(test.name);

    if !out_dir.join(".git").is_dir() {
        let status = Command::new("git")
            .arg("init")
            .arg(&out_dir)
            .status()
            .expect("");
        assert!(status.success());
    }

    // Try progressively deeper fetch depths to find the commit
    let mut found = false;
    for depth in &[0, 1, 10, 100, 1000, 100000] {
        if *depth > 0 {
            let status = Command::new("git")
                .arg("fetch")
                .arg(test.repo)
                .arg("master")
                .arg(&format!("--depth={}", depth))
                .current_dir(&out_dir)
                .status()
                .expect("");
            assert!(status.success());
        }

        let status = Command::new("git")
            .arg("reset")
            .arg(test.sha)
            .arg("--hard")
            .current_dir(&out_dir)
            .status()
            .expect("");

        if status.success() {
            found = true;
            break;
        }
    }

    if !found {
        panic!("unable to find commit {}", test.sha)
    }
    let status = Command::new("git")
        .arg("clean")
        .arg("-fdx")
        .current_dir(&out_dir)
        .status()
        .unwrap();
    assert!(status.success());

    out_dir
}

fn run_cargo_test(cargo_path: &Path, crate_path: &Path) -> bool {
    let status = Command::new(cargo_path)
        .arg("test")
        // Disable rust-lang/cargo's cross-compile tests
        .env("CFG_DISABLE_CROSS_TESTS", "1")
        .current_dir(crate_path)
        .status()
        .expect("");

    status.success()
}
<|endoftext|>


<commit_before>#![cfg_attr(all(test, feature = "nightly"), feature(test))] // we only need test feature when testing

#[macro_use] extern crate log;

extern crate syntex_syntax;
extern crate toml;
extern crate env_logger;

extern crate racer;

#[cfg(not(test))]
use racer::core;
#[cfg(not(test))]
use racer::util;
#[cfg(not(test))]
use racer::core::Match;
#[cfg(not(test))]
use racer::util::{getline, path_exists};
#[cfg(not(test))]
use racer::nameres::{do_file_search, do_external_search, PATH_SEP};
#[cfg(not(test))]
use racer::scopes;
#[cfg(not(test))]
use std::path::Path;

#[cfg(not(test))]
fn match_with_snippet_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }

    let snippet = racer::snippets::snippet_for_match(&m);
    println!("MATCH {};{};{};{};{};{:?};{}", m.matchstr,
                                    snippet,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn match_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    println!("MATCH {},{},{},{},{:?},{}", m.matchstr,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn complete(match_found: &Fn(Match), args: &[String]) {
    if args.len() < 1 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    match args[1].parse::<usize>() {
        Ok(linenum) => {
            // input: linenum, colnum, fname
            if args.len() < 4 {
                println!("Provide more arguments!");
                print_usage();
                std::process::exit(1);
            }
            let charnum = args[2].parse::<usize>().unwrap();
            let fname = &args[3];
            let substitute_file = Path::new(match args.len() > 4 {
                true => &args[4],
                false => fname
            });
            let fpath = Path::new(fname);
            let src = core::load_file(&substitute_file);
            let line = &*getline(&substitute_file, linenum);
            let (start, pos) = util::expand_ident(line, charnum);
            println!("PREFIX {},{},{}", start, pos, &line[start..pos]);

            let session = core::Session::from_path(&fpath, &substitute_file);
            let point = scopes::coords_to_point(&*src, linenum, charnum);
            for m in core::complete_from_file(&*src, &fpath, point, &session) {
                match_found(m);
            }
            println!("END");
        }
        Err(_) => {
            // input: a command line string passed in
            let arg = &args[1];
            let it = arg.split("::");
            let p: Vec<&str> = it.collect();

            for m in do_file_search(p[0], &Path::new(".")) {
                if p.len() == 1 {
                    match_found(m);
                } else {
                    for m in do_external_search(&p[1..], &m.filepath, m.point, core::SearchType::StartsWith, core::Namespace::BothNamespaces, &m.session) {
                        match_found(m);
                    }
                }
            }
        }
    }
}

#[cfg(not(test))]
fn prefix(args: &[String]) {
    if args.len() < 4 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[1].parse::<usize>().unwrap();
    let charnum = args[2].parse::<usize>().unwrap();
    let fname = &args[3];

    // print the start, end, and the identifier prefix being matched
    let path = Path::new(fname);
    let line = &*getline(&path, linenum);
    let (start, pos) = util::expand_ident(line, charnum);
    println!("PREFIX {},{},{}", start, pos, &line[start..pos]);
}

#[cfg(not(test))]
fn find_definition(args: &[String]) {
    if args.len() < 4 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[1].parse::<usize>().unwrap();
    let charnum = args[2].parse::<usize>().unwrap();
    let fname = &args[3];
    let substitute_file = Path::new(match args.len() > 4 {
        true => &args[4],
        false => fname
    });
    let fpath = Path::new(&fname);
    let session = core::Session::from_path(&fpath, &substitute_file);
    let src = core::load_file(&substitute_file);
    let pos = scopes::coords_to_point(&*src, linenum, charnum);

    core::find_definition(&*src, &fpath, pos, &session).map(match_fn);
    println!("END");
}

#[cfg(not(test))]
fn print_usage() {
    let program = std::env::args().next().unwrap().clone();
    println!("usage: {} complete linenum charnum fname [substitute_file]", program);
    println!("or:    {} find-definition linenum charnum fname [substitute_file]", program);
    println!("or:    {} complete fullyqualifiedname   (e.g. std::io::)", program);
    println!("or:    {} prefix linenum charnum fname", program);
    println!("or replace complete with complete-with-snippet for more detailed completions.");
    println!("or:    {} daemon     - to start a process that receives the above commands via stdin", program);
}

#[cfg(not(test))]
fn check_rust_src_env_var() {
    if let Ok(srcpaths) = std::env::var("RUST_SRC_PATH") {
        let v = srcpaths.split(PATH_SEP).collect::<Vec<_>>();
        if !v.is_empty() {
            let f = Path::new(v[0]);
            if !path_exists(f) {
                println!("racer can't find the directory pointed to by the RUST_SRC_PATH variable \"{}\". Try using an absolute fully qualified path and make sure it points to the src directory of a rust checkout - e.g. \"/home/foouser/src/rust/src\".", srcpaths);
                std::process::exit(1);
            } else if !path_exists(f.join("libstd")) {
                println!("Unable to find libstd under RUST_SRC_PATH. N.B. RUST_SRC_PATH variable needs to point to the *src* directory inside a rust checkout e.g. \"/home/foouser/src/rust/src\". Current value \"{}\"", srcpaths);
                std::process::exit(1);
            }
        }
    } else {
        println!("RUST_SRC_PATH environment variable must be set to point to the src directory of a rust checkout. E.g. \"/home/foouser/src/rust/src\"");
        std::process::exit(1);
    }
}

#[cfg(not(test))]
fn daemon() {
    use std::io;
    let mut input = String::new();
    while let Ok(n) = io::stdin().read_line(&mut input) {
        if n == 0 {
            break;
        }
        let args: Vec<String> = input.split(" ").map(|s| s.trim().to_string()).collect();
        run(&args);

        input.clear();
    }
}

#[cfg(not(test))]
fn main() {
    env_logger::init().unwrap();
    check_rust_src_env_var();

    let args: Vec<String> = std::env::args().collect();

    if args.len() == 1 {
        print_usage();
        std::process::exit(1);
    }

    let args = &args[1..];
    run(args);
}

fn run(args: &[String]) {
    let command  = &args[0];
    match &command[..] {
        "daemon" => daemon(),
        "prefix" => prefix(&args),
        "complete" => complete(&match_fn, &args),
        "complete-with-snippet" => complete(&match_with_snippet_fn, &args),
        "find-definition" => find_definition(&args),
        "help" => print_usage(),
        cmd => {
            println!("Sorry, I didn't understand command {}", cmd);
            print_usage();
            std::process::exit(1);
        }
    }
}
<commit_msg>Oops, get tests working again<commit_after>#![cfg_attr(all(test, feature = "nightly"), feature(test))] // we only need test feature when testing

#[macro_use] extern crate log;

extern crate syntex_syntax;
extern crate toml;
extern crate env_logger;

extern crate racer;

#[cfg(not(test))]
use racer::core;
#[cfg(not(test))]
use racer::util;
#[cfg(not(test))]
use racer::core::Match;
#[cfg(not(test))]
use racer::util::{getline, path_exists};
#[cfg(not(test))]
use racer::nameres::{do_file_search, do_external_search, PATH_SEP};
#[cfg(not(test))]
use racer::scopes;
#[cfg(not(test))]
use std::path::Path;

#[cfg(not(test))]
fn match_with_snippet_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }

    let snippet = racer::snippets::snippet_for_match(&m);
    println!("MATCH {};{};{};{};{};{:?};{}", m.matchstr,
                                    snippet,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn match_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    println!("MATCH {},{},{},{},{:?},{}", m.matchstr,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn complete(match_found: &Fn(Match), args: &[String]) {
    if args.len() < 1 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    match args[1].parse::<usize>() {
        Ok(linenum) => {
            // input: linenum, colnum, fname
            if args.len() < 4 {
                println!("Provide more arguments!");
                print_usage();
                std::process::exit(1);
            }
            let charnum = args[2].parse::<usize>().unwrap();
            let fname = &args[3];
            let substitute_file = Path::new(match args.len() > 4 {
                true => &args[4],
                false => fname
            });
            let fpath = Path::new(fname);
            let src = core::load_file(&substitute_file);
            let line = &*getline(&substitute_file, linenum);
            let (start, pos) = util::expand_ident(line, charnum);
            println!("PREFIX {},{},{}", start, pos, &line[start..pos]);

            let session = core::Session::from_path(&fpath, &substitute_file);
            let point = scopes::coords_to_point(&*src, linenum, charnum);
            for m in core::complete_from_file(&*src, &fpath, point, &session) {
                match_found(m);
            }
            println!("END");
        }
        Err(_) => {
            // input: a command line string passed in
            let arg = &args[1];
            let it = arg.split("::");
            let p: Vec<&str> = it.collect();

            for m in do_file_search(p[0], &Path::new(".")) {
                if p.len() == 1 {
                    match_found(m);
                } else {
                    for m in do_external_search(&p[1..], &m.filepath, m.point, core::SearchType::StartsWith, core::Namespace::BothNamespaces, &m.session) {
                        match_found(m);
                    }
                }
            }
        }
    }
}

#[cfg(not(test))]
fn prefix(args: &[String]) {
    if args.len() < 4 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[1].parse::<usize>().unwrap();
    let charnum = args[2].parse::<usize>().unwrap();
    let fname = &args[3];

    // print the start, end, and the identifier prefix being matched
    let path = Path::new(fname);
    let line = &*getline(&path, linenum);
    let (start, pos) = util::expand_ident(line, charnum);
    println!("PREFIX {},{},{}", start, pos, &line[start..pos]);
}

#[cfg(not(test))]
fn find_definition(args: &[String]) {
    if args.len() < 4 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[1].parse::<usize>().unwrap();
    let charnum = args[2].parse::<usize>().unwrap();
    let fname = &args[3];
    let substitute_file = Path::new(match args.len() > 4 {
        true => &args[4],
        false => fname
    });
    let fpath = Path::new(&fname);
    let session = core::Session::from_path(&fpath, &substitute_file);
    let src = core::load_file(&substitute_file);
    let pos = scopes::coords_to_point(&*src, linenum, charnum);

    core::find_definition(&*src, &fpath, pos, &session).map(match_fn);
    println!("END");
}

#[cfg(not(test))]
fn print_usage() {
    let program = std::env::args().next().unwrap().clone();
    println!("usage: {} complete linenum charnum fname [substitute_file]", program);
    println!("or:    {} find-definition linenum charnum fname [substitute_file]", program);
    println!("or:    {} complete fullyqualifiedname   (e.g. std::io::)", program);
    println!("or:    {} prefix linenum charnum fname", program);
    println!("or replace complete with complete-with-snippet for more detailed completions.");
    println!("or:    {} daemon     - to start a process that receives the above commands via stdin", program);
}

#[cfg(not(test))]
fn check_rust_src_env_var() {
    if let Ok(srcpaths) = std::env::var("RUST_SRC_PATH") {
        let v = srcpaths.split(PATH_SEP).collect::<Vec<_>>();
        if !v.is_empty() {
            let f = Path::new(v[0]);
            if !path_exists(f) {
                println!("racer can't find the directory pointed to by the RUST_SRC_PATH variable \"{}\". Try using an absolute fully qualified path and make sure it points to the src directory of a rust checkout - e.g. \"/home/foouser/src/rust/src\".", srcpaths);
                std::process::exit(1);
            } else if !path_exists(f.join("libstd")) {
                println!("Unable to find libstd under RUST_SRC_PATH. N.B. RUST_SRC_PATH variable needs to point to the *src* directory inside a rust checkout e.g. \"/home/foouser/src/rust/src\". Current value \"{}\"", srcpaths);
                std::process::exit(1);
            }
        }
    } else {
        println!("RUST_SRC_PATH environment variable must be set to point to the src directory of a rust checkout. E.g. \"/home/foouser/src/rust/src\"");
        std::process::exit(1);
    }
}

#[cfg(not(test))]
fn daemon() {
    use std::io;
    let mut input = String::new();
    while let Ok(n) = io::stdin().read_line(&mut input) {
        if n == 0 {
            break;
        }
        let args: Vec<String> = input.split(" ").map(|s| s.trim().to_string()).collect();
        run(&args);

        input.clear();
    }
}

#[cfg(not(test))]
fn main() {
    env_logger::init().unwrap();
    check_rust_src_env_var();

    let args: Vec<String> = std::env::args().collect();

    if args.len() == 1 {
        print_usage();
        std::process::exit(1);
    }

    let args = &args[1..];
    run(args);
}

#[cfg(not(test))]
fn run(args: &[String]) {
    let command  = &args[0];
    match &command[..] {
        "daemon" => daemon(),
        "prefix" => prefix(&args),
        "complete" => complete(&match_fn, &args),
        "complete-with-snippet" => complete(&match_with_snippet_fn, &args),
        "find-definition" => find_definition(&args),
        "help" => print_usage(),
        cmd => {
            println!("Sorry, I didn't understand command {}", cmd);
            print_usage();
            std::process::exit(1);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add test: Samurai Sudoku.<commit_after>//! Samurai Sudoku.
//!
//! https://en.wikipedia.org/wiki/Sudoku#Variants
//! http://www.samurai-sudoku.com/#ai

extern crate puzzle_solver;

use puzzle_solver::{Puzzle,Solution,VarToken};

const SQRT_SIZE: usize = 3;
const SIZE: usize = 9;
const X: i32 = -1;
type Board = [[i32; SIZE + SQRT_SIZE + SIZE]; SIZE + SQRT_SIZE + SIZE];
type SudokuVars = Vec<Vec<VarToken>>;
type SamuraiVars = (SudokuVars, SudokuVars, SudokuVars, SudokuVars, SudokuVars);

fn make_sudoku(sys: &mut Puzzle) -> SudokuVars {
    let vars = sys.new_vars_with_candidates_2d(SIZE, SIZE, &[1,2,3,4,5,6,7,8,9]);

    for y in 0..SIZE {
        sys.all_different(&vars[y]);
    }

    for x in 0..SIZE {
        sys.all_different(vars.iter().map(|row| &row[x]));
    }

    for block in 0..SIZE {
        let x0 = SQRT_SIZE * (block % SQRT_SIZE);
        let y0 = SQRT_SIZE * (block / SQRT_SIZE);
        sys.all_different((0..SIZE).map(|n|
                &vars[y0 + (n / SQRT_SIZE)][x0 + (n % SQRT_SIZE)]));
    }

    vars
}

fn make_samurai_sudoku(board: &Board) -> (Puzzle, SamuraiVars) {
    let set = |sys: &mut Puzzle, var, val| if val != 0 { sys.set_value(var, val) };

    let mut sys = Puzzle::new();
    let tl = make_sudoku(&mut sys);
    let tr = make_sudoku(&mut sys);
    let bl = make_sudoku(&mut sys);
    let br = make_sudoku(&mut sys);
    let mid = make_sudoku(&mut sys);

    for y in 0..SQRT_SIZE {
        for x in 0..SQRT_SIZE {
            sys.equals(mid[0 * SQRT_SIZE + y][0 * SQRT_SIZE + x], tl[2 * SQRT_SIZE + y][2 * SQRT_SIZE + x]);
            sys.equals(mid[0 * SQRT_SIZE + y][2 * SQRT_SIZE + x], tr[2 * SQRT_SIZE + y][0 * SQRT_SIZE + x]);
            sys.equals(mid[2 * SQRT_SIZE + y][0 * SQRT_SIZE + x], bl[0 * SQRT_SIZE + y][2 * SQRT_SIZE + x]);
            sys.equals(mid[2 * SQRT_SIZE + y][2 * SQRT_SIZE + x], br[0 * SQRT_SIZE + y][0 * SQRT_SIZE + x]);
        }
    }

    for y in 0..SIZE {
        for x in 0..SIZE {
            set(&mut sys, tl[y][x], board[y][x]);
            set(&mut sys, tr[y][x], board[y][SIZE + SQRT_SIZE + x]);
            set(&mut sys, bl[y][x], board[SIZE + SQRT_SIZE + y][x]);
            set(&mut sys, br[y][x], board[SIZE + SQRT_SIZE + y][SIZE + SQRT_SIZE + x]);
            set(&mut sys, mid[y][x], board[2 * SQRT_SIZE + y][2 * SQRT_SIZE + x]);
        }
    }

    (sys, (tl, tr, bl, br, mid))
}

fn print_samurai_sudoku(dict: &Solution, vars: &SamuraiVars) {
    let &(ref tl, ref tr, ref bl, ref br, ref mid) = vars;
    let pr3 = |a: &[VarToken], j| print!(" {}{}{}", dict[a[j]], dict[a[j + 1]], dict[a[j + 2]]);
    let pr9 = |a| { pr3(a, 0); pr3(a, 3); pr3(a, 6); };
    let gap = || print!("    ");

    for i in 0..SIZE {
        pr9(&tl[i]);
        if 2 * SQRT_SIZE <= i {
            pr3(&mid[i - 2 * SQRT_SIZE], 3);
        } else {
            gap();
        }
        pr9(&tr[i]);
        println!();
    }

    for i in SQRT_SIZE..(2 * SQRT_SIZE) {
        gap();
        gap();
        pr9(&mid[i]);
        println!();
    }

    for i in 0..SIZE {
        pr9(&bl[i]);
        if i < SQRT_SIZE {
            pr3(&mid[2 * SQRT_SIZE + i], 3);
        } else {
            gap();
        }
        pr9(&br[i]);
        println!();
    }
}

fn verify_samurai_sudoku(dict: &Solution, vars: &SamuraiVars, expected: &Board) {
    let &(ref tl, ref tr, ref bl, ref br, ref mid) = vars;
    for i in 0..SIZE {
        for j in 0..SIZE {
            assert_eq!(dict[tl[i][j]], expected[i][j]);
            assert_eq!(dict[tr[i][j]], expected[i][SIZE + SQRT_SIZE + j]);
            assert_eq!(dict[bl[i][j]], expected[SIZE + SQRT_SIZE + i][j]);
            assert_eq!(dict[br[i][j]], expected[SIZE + SQRT_SIZE + i][SIZE + SQRT_SIZE + j]);
            assert_eq!(dict[mid[i][j]], expected[2 * SQRT_SIZE + i][2 * SQRT_SIZE + j]);
        }
    }
}

#[test]
fn samuraisudoku_easy() {
    let puzzle = [
        [ 0,0,3,  0,0,0,  2,0,0,  X,X,X,  0,0,6,  0,0,0,  2,0,0 ],
        [ 0,2,0,  4,0,8,  0,3,0,  X,X,X,  0,3,0,  4,0,2,  0,8,0 ],
        [ 8,0,0,  0,9,0,  0,0,4,  X,X,X,  8,0,0,  0,1,0,  0,0,4 ],

        [ 0,5,0,  6,0,1,  0,2,0,  X,X,X,  0,2,0,  1,0,7,  0,9,0 ],
        [ 0,0,8,  0,0,0,  6,0,0,  X,X,X,  0,0,9,  0,0,0,  8,0,0 ],
        [ 0,7,0,  8,0,4,  0,1,0,  X,X,X,  0,8,0,  5,0,9,  0,4,0 ],

        [ 1,0,0,  0,7,0,  0,0,0,  0,0,0,  0,0,0,  0,7,0,  0,0,5 ],
        [ 0,4,0,  1,0,2,  0,0,0,  0,0,0,  0,0,0,  2,0,8,  0,7,0 ],
        [ 0,0,9,  0,0,0,  0,0,0,  0,6,0,  0,0,0,  0,0,0,  1,0,0 ],

        [ X,X,X,  X,X,X,  0,0,0,  5,0,1,  0,0,0,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  0,0,9,  0,0,0,  6,0,0,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  0,0,0,  3,0,6,  0,0,0,  X,X,X,  X,X,X ],

        [ 0,0,8,  0,0,0,  0,0,0,  0,7,0,  0,0,0,  0,0,0,  4,0,0 ],
        [ 0,4,0,  5,0,1,  0,0,0,  0,0,0,  0,0,0,  9,0,5,  0,7,0 ],
        [ 6,0,0,  0,2,0,  0,0,0,  0,0,0,  0,0,0,  0,6,0,  0,0,9 ],

        [ 0,9,0,  1,0,3,  0,7,0,  X,X,X,  0,7,0,  5,0,1,  0,9,0 ],
        [ 0,0,5,  0,0,0,  1,0,0,  X,X,X,  0,0,3,  0,0,0,  6,0,0 ],
        [ 0,1,0,  6,0,8,  0,9,0,  X,X,X,  0,2,0,  8,0,6,  0,1,0 ],

        [ 5,0,0,  0,7,0,  0,0,6,  X,X,X,  7,0,0,  0,2,0,  0,0,5 ],
        [ 0,2,0,  3,0,5,  0,1,0,  X,X,X,  0,9,0,  6,0,4,  0,3,0 ],
        [ 0,0,6,  0,0,0,  2,0,0,  X,X,X,  0,0,4,  0,0,0,  1,0,0 ] ];

    let expected = [
        [ 4,9,3,  7,1,5,  2,6,8,  X,X,X,  9,4,6,  8,3,5,  2,1,7 ],
        [ 5,2,7,  4,6,8,  9,3,1,  X,X,X,  1,3,7,  4,9,2,  5,8,6 ],
        [ 8,6,1,  2,9,3,  5,7,4,  X,X,X,  8,5,2,  7,1,6,  9,3,4 ],

        [ 9,5,4,  6,3,1,  8,2,7,  X,X,X,  5,2,4,  1,8,7,  6,9,3 ],
        [ 3,1,8,  9,2,7,  6,4,5,  X,X,X,  7,1,9,  6,4,3,  8,5,2 ],
        [ 2,7,6,  8,5,4,  3,1,9,  X,X,X,  6,8,3,  5,2,9,  7,4,1 ],

        [ 1,8,2,  3,7,9,  4,5,6,  7,1,3,  2,9,8,  3,7,1,  4,6,5 ],
        [ 6,4,5,  1,8,2,  7,9,3,  8,5,2,  4,6,1,  2,5,8,  3,7,9 ],
        [ 7,3,9,  5,4,6,  1,8,2,  9,6,4,  3,7,5,  9,6,4,  1,2,8 ],

        [ X,X,X,  X,X,X,  6,4,8,  5,9,1,  7,2,3,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  3,1,9,  2,8,7,  6,5,4,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  2,7,5,  3,4,6,  1,8,9,  X,X,X,  X,X,X ],

        [ 1,7,8,  9,3,6,  5,2,4,  1,7,8,  9,3,6,  2,8,7,  4,5,1 ],
        [ 2,4,3,  5,8,1,  9,6,7,  4,3,5,  8,1,2,  9,4,5,  3,7,6 ],
        [ 6,5,9,  4,2,7,  8,3,1,  6,2,9,  5,4,7,  1,6,3,  8,2,9 ],

        [ 8,9,2,  1,4,3,  6,7,5,  X,X,X,  6,7,8,  5,3,1,  2,9,4 ],
        [ 4,6,5,  7,9,2,  1,8,3,  X,X,X,  1,5,3,  4,9,2,  6,8,7 ],
        [ 3,1,7,  6,5,8,  4,9,2,  X,X,X,  4,2,9,  8,7,6,  5,1,3 ],

        [ 5,8,1,  2,7,9,  3,4,6,  X,X,X,  7,6,1,  3,2,8,  9,4,5 ],
        [ 9,2,4,  3,6,5,  7,1,8,  X,X,X,  2,9,5,  6,1,4,  7,3,8 ],
        [ 7,3,6,  8,1,4,  2,5,9,  X,X,X,  3,8,4,  7,5,9,  1,6,2 ] ];

    let (mut sys, vars) = make_samurai_sudoku(&puzzle);
    let dict = sys.solve_any().expect("solution");
    print_samurai_sudoku(&dict, &vars);
    verify_samurai_sudoku(&dict, &vars, &expected);
    println!("samuraisudoku_easy: {} guesses", sys.num_guesses());
}
<|endoftext|>


<commit_before><commit_msg>Import early l20n FTL parsing code.<commit_after>pub enum Expression {
    IdentifierExpression {
        name: String,
    },
}

pub enum PatternElement {
    TextElement {
        value: String,
    },
    Placeable {
        expressions: Vec<Expression>,
    },
}

pub enum Value {
    Pattern {
        source: String,
        elements: Vec<PatternElement>,
    },
}

pub enum Entry {
    Entity {
        id: Identifier,
        value: Value,
    },
}

pub struct Identifier {
    pub name: String,
}

pub struct Parser<'a> {
    source: std::str::Chars<'a>,
    ch: Option<char>,
    pos: u16,
}

impl<'a> Parser<'a> {
    pub fn new(source: &'a str) -> Parser<'a> {
        Parser {
            source: source.chars(),
            ch: None,
            pos: 0,
        }
    }

    fn bump(&mut self) {
        self.ch = self.source.next();

        self.pos += 1;
    }

    fn ch_is(&self, ch: char) -> bool {
        self.ch == Some(ch)
    }

    fn get_ws(&mut self) {
        while self.ch_is(' ') || self.ch_is('\n') || self.ch_is('\t') || self.ch_is('\r') {
            self.bump();
        }
    }

    fn get_line_ws(&mut self) {
        while self.ch_is(' ') || self.ch_is('\t') {
            self.bump();
        }
    }

    pub fn parse(&mut self) -> Vec<Entry> {
        let mut entries: Vec<Entry> = Vec::new();

        self.get_ws();

        self.bump();

        loop {
            if self.ch == None {
                break;
            }

            entries.push(self.get_entry());
            self.get_ws();
        }
        entries
    }

    fn get_entry(&mut self) -> Entry {
        let val = self.get_entity();

        val
    }

    fn get_entity(&mut self) -> Entry {
        let id = self.get_identifier();
        self.get_line_ws();

        if !self.ch_is('=') {
            panic!();
        }
        self.bump();

        self.get_line_ws();

        let value = self.get_pattern();

        Entry::Entity {
            id: id,
            value: value,
        }
    }

    fn get_identifier(&mut self) -> Identifier {
        let mut name = String::new();

        let ch = match self.ch {
            Some(c) => c,
            None => panic!(),
        };

        match ch {
            'a'...'z' | 'A'...'Z' | '_' => name.push(ch),
            _ => return Identifier { name: name },
        }
        self.bump();

        loop {
            let ch = match self.ch {
                Some(c) => c,
                None => break,
            };

            match ch {
                'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '-' => name.push(ch),
                _ => break,
            }
            self.bump();
        }

        Identifier { name: name }
    }

    fn get_pattern(&mut self) -> Value {
        let mut buffer = String::new();
        let mut source = String::new();
        let mut content = vec![];
        let mut quote_delimited: bool = false;
        let mut first_line = true;

        if self.ch_is('"') {
            quote_delimited = true;
        }

        loop {
            match self.ch {
                Some(c) if c == '\n' => {
                    if quote_delimited {
                        panic!("Unclosed string");
                    }
                    self.bump();
                    self.get_line_ws();

                    if !self.ch_is('|') {
                        break;
                    }
                    if first_line && buffer.len() != 0 {
                        panic!("Multiline string should have the ID line empty");
                    }
                    first_line = false;
                    self.bump();
                    if self.ch_is(' ') {
                        self.bump();
                    }
                    if buffer.len() != 0 {
                        buffer.push('\n');
                    }
                    continue;
                }
                Some(c) if c == '"' => {
                    self.bump();
                    quote_delimited = false;
                    break;
                }
                Some(c) => source.push(c),
                None => break,
            }
            match self.ch {
                Some(c) => buffer.push(c),
                None => continue,
            };
            self.bump();
        }

        if quote_delimited {
            panic!("Unclosed string");
        }

        if buffer.len() != 0 {
            // source.append(buffer);
            content.push(PatternElement::TextElement { value: source.clone() });
        }

        if content.len() == 0 {
            // return Value::Pattern(source: source, elements: content);
        }

        content.push(PatternElement::TextElement { value: source.clone() });

        Value::Pattern {
            source: source,
            elements: content,
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add problem #113<commit_after>#[crate_type = "rlib"];

use std::vec;
use std::iter::AdditiveIterator;

pub static EXPECTED_ANSWER: &'static str = "51161058134250";

fn num_increasing(len: uint) -> uint {
    let mut buf = vec::from_fn(len, |_| [0u, ..10]);

    for d in range(0, buf[0].len()) {
        buf[0][d] = 1;
    }
    for i in range(1, len) {
        let mut s = 0;
        for d in range(0, buf[i].len()).invert() {
            s += buf[i - 1][d];
            buf[i][d] = s;
        }
    }

    let sum = range(0, buf[len - 1].len())
        .map(|d| buf[len - 1][d])
        .sum();
    sum - 1 // all zero
}

fn num_decreasing(len: uint) -> uint {
    let mut buf = vec::from_fn(len, |_| [0u, ..11]); // 0, 1, 2, .., 9, A

    for d in range(0, buf[0].len()) {
        buf[0][d] = 1;
    }
    for i in range(1, len) {
        let mut s = 0;
        for d in range(0, buf[i].len()) {
            s += buf[i - 1][d];
            buf[i][d] = s;
        }
    }

    let sum = range(0, buf[len - 1].len())
        .map(|d| buf[len - 1][d])
        .sum();

    sum - len // A のみからなるものを取り除く
        - 1   // all zero
}

fn num_nonbouncy(len: uint) -> uint {
    let num_incr = num_increasing(len);
    let num_decr = num_decreasing(len);
    let num_incr_and_decr = 9 * len;
    num_incr + num_decr - num_incr_and_decr
}

pub fn solve() -> ~str {
    num_nonbouncy(100).to_str()
}

#[cfg(test)]
mod test {
    use super::num_nonbouncy;

    #[test]
    fn test_nonbouncy() {
        assert_eq!(12951,  num_nonbouncy(6));
        assert_eq!(277032, num_nonbouncy(10));
    }
}
<|endoftext|>