<commit_before>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::fmt::Debug;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::async::Server;

use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};
use futures_cpupool::CpuPool;

use std::sync::{RwLock, Arc};
use std::time::Duration;
use std::thread;
use std::rc::Rc;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let server = Server::bind("localhost:8081", &handle).unwrap();
    let pool = Rc::new(CpuPool::new_num_cpus());
    let state = Arc::new(RwLock::new(State::new()));
    let (read_channel_out, read_channel_in) = futures::sync::mpsc::unbounded();
    let (write_channel_out, write_channel_in) = futures::sync::mpsc::unbounded();
    let connection_handler = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(|(upgrade, addr)| {
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle);
                return Ok(());
            }
            let read_channel_out = read_channel_out.clone();
            let write_channel_out = write_channel_out.clone();
            let handle_inner = handle.clone();
            let f = upgrade
                .use_protocol("rust-websocket")
                .accept()
                .and_then(move |(framed, _)| {
                    let (sink, stream) = framed.split();
                    let f = read_channel_out.send(stream);
                    spawn_future(f, "Register client listener", &handle_inner);
                    let f = write_channel_out.send(sink);
                    spawn_future(f, "Register client sender", &handle_inner);
                    Ok(())
                });
            spawn_future(f, "Client Connections", &handle);
            Ok(())
        })
        .map_err(|_| ());

    let state_read = state.clone();
    let read_handler = pool.spawn_fn(move || {
        read_channel_in.for_each(move |stream| {
            let state_read = state_read.clone();
            stream.for_each(move |msg|{
                    handle_incoming(&mut state_read.write().unwrap(), &msg);
                    Ok(())
            }).map_err(|_| ())
        })
    });
    let write_handler = pool.spawn_fn(move || {
        write_channel_in.for_each(move |sink| {
            let state_write = state.clone();
            future::loop_fn(sink, move |sink| {
                thread::sleep(Duration::from_secs(4));
                send(&state_write.read().unwrap(), sink)
                    .map(|sink| {
                        match 1 {
                            1 => Loop::Continue(sink),
                            _ => Loop::Break(())
                        }
                    })
            }).map_err(|_| ())
        })
    });
    let handlers = connection_handler.join3(read_handler, write_handler);

    core.run(handlers).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &OwnedMessage) {
    match msg {
        &OwnedMessage::Text(ref txt) => {
            println!("Received message: {}", txt);
            state.msg = txt.clone();
        }
        _ => {}
    }
}

type SplitSink = futures::stream::SplitSink<
                    websocket::client::async::Framed<tokio_core::net::TcpStream,
                    websocket::async::MessageCodec<websocket::OwnedMessage>>
                >;

fn send(state: &State, sink: SplitSink) -> futures::sink::Send<SplitSink> {
    let msg = serde_json::to_string(&state).unwrap();
    println!("Sending message: {}", msg);
    sink.send(OwnedMessage::Text(msg))
}

#[derive(Serialize)]
struct State {
    msg: String,
}

impl State {
    fn new() -> State {
        State { msg: "git gud".to_string() }
    }
}
<commit_msg>Core: Fix not listening to multiple clients<commit_after>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::async::Server;

use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};
use futures_cpupool::CpuPool;

use std::sync::{RwLock, Arc};
use std::thread;
use std::rc::Rc;
use std::fmt::Debug;
use std::time::Duration;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let remote = core.remote();
    let server = Server::bind("localhost:8081", &handle).unwrap();
    let pool = Rc::new(CpuPool::new_num_cpus());
    let state = Arc::new(RwLock::new(State::new()));
    let (read_channel_out, read_channel_in) = futures::sync::mpsc::unbounded();
    let (write_channel_out, write_channel_in) = futures::sync::mpsc::unbounded();
    let handle_inner = handle.clone();
    let connection_handler = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(move |(upgrade, addr)| {
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle_inner);
                return Ok(());
            }
            let read_channel_out = read_channel_out.clone();
            let write_channel_out = write_channel_out.clone();
            upgrade
                .use_protocol("rust-websocket")
                .accept()
                .and_then(move |(framed, _)| {
                    let (sink, stream) = framed.split();
                    read_channel_out.send(stream).wait().unwrap();
                    write_channel_out.send(sink).wait().unwrap();
                    Ok(())
                })
                .wait()
                .unwrap();
            Ok(())
        })
        .map_err(|_| ());

    let state_read = state.clone();
    let remote_write = remote.clone();
    let read_handler = pool.spawn_fn( || {
        read_channel_in.for_each(move |stream| {
            let state_read = state_read.clone();
            remote_write.spawn(|_| {
                stream
                    .for_each(move |msg|{
                        handle_incoming(&mut state_read.write().unwrap(), &msg);
                        Ok(())
                    })
                    .map_err(|_| ())
            });
            Ok(())
        })
    });

    let write_handler = pool.spawn_fn(move || {
        write_channel_in.for_each(move |sink| {
            let state_write = state.clone();
            future::loop_fn(sink, move |sink| {
                thread::sleep(Duration::from_millis(100));
                send(&state_write.read().unwrap(), sink)
                    .map(|sink| {
                        Loop::Continue(sink)
                    })
                    .map_err(|_| Loop::Break::<(), SplitSink>(()))
            }).map_err(|_| ())
        })
    });

    let handlers = connection_handler.select2(read_handler.select(write_handler));
    core.run(handlers).map_err(|_| println!("err")).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &OwnedMessage) {
    match msg {
        &OwnedMessage::Text(ref txt) => {
            println!("Received message: {}", txt);
            state.msg = txt.clone();
        }
        _ => {}
    }
}

type SplitSink = futures::stream::SplitSink<
                    websocket::client::async::Framed<tokio_core::net::TcpStream,
                    websocket::async::MessageCodec<websocket::OwnedMessage>>
                >;

fn send(state: &State, sink: SplitSink) -> futures::sink::Send<SplitSink> {
    let msg = serde_json::to_string(&state).unwrap();
    println!("Sending message: {}", msg);
    sink.send(OwnedMessage::Text(msg))
}

#[derive(Serialize)]
struct State {
    msg: String,
}

impl State {
    fn new() -> State {
        State { msg: "git gud".to_string() }
    }
}
<|endoftext|>


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

#![allow(non_snake_case)]

register_diagnostic!(E0001, r##"
    This error suggests that the expression arm corresponding to the noted pattern
    will never be reached as for all possible values of the expression being matched,
    one of the preceeding patterns will match.

    This means that perhaps some of the preceeding patterns are too general, this
    one is too specific or the ordering is incorrect.
"##)

register_diagnostics!(
    E0002,
    E0003,
    E0004,
    E0005,
    E0006,
    E0007,
    E0008,
    E0009,
    E0010,
    E0011,
    E0012,
    E0013,
    E0014,
    E0015,
    E0016,
    E0017,
    E0018,
    E0019,
    E0020,
    E0022,
    E0023,
    E0024,
    E0025,
    E0026,
    E0027,
    E0029,
    E0030,
    E0031,
    E0033,
    E0034,
    E0035,
    E0036,
    E0038,
    E0040,
    E0044,
    E0045,
    E0046,
    E0049,
    E0050,
    E0051,
    E0052,
    E0053,
    E0054,
    E0055,
    E0056,
    E0057,
    E0059,
    E0060,
    E0061,
    E0062,
    E0063,
    E0066,
    E0067,
    E0068,
    E0069,
    E0070,
    E0071,
    E0072,
    E0073,
    E0074,
    E0075,
    E0076,
    E0077,
    E0079,
    E0080,
    E0081,
    E0082,
    E0083,
    E0084,
    E0085,
    E0086,
    E0087,
    E0088,
    E0089,
    E0090,
    E0091,
    E0092,
    E0093,
    E0094,
    E0100,
    E0101,
    E0102,
    E0103,
    E0104,
    E0106,
    E0107,
    E0108,
    E0109,
    E0110,
    E0116,
    E0117,
    E0118,
    E0119,
    E0120,
    E0121,
    E0122,
    E0124,
    E0127,
    E0128,
    E0129,
    E0130,
    E0131,
    E0132,
    E0133,
    E0134,
    E0135,
    E0136,
    E0137,
    E0138,
    E0139,
    E0140,
    E0141,
    E0152,
    E0153,
    E0157,
    E0158,
    E0159,
    E0161,
    E0162,
    E0163,
    E0164,
    E0165,
    E0166,
    E0167,
    E0168,
    E0169,
    E0170,
    E0171,
    E0172,
    E0173,
    E0174,
    E0177,
    E0178
)
<commit_msg>Remove diagnostic errors that were yielding warnings.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_snake_case)]

register_diagnostic!(E0001, r##"
    This error suggests that the expression arm corresponding to the noted pattern
    will never be reached as for all possible values of the expression being matched,
    one of the preceeding patterns will match.

    This means that perhaps some of the preceeding patterns are too general, this
    one is too specific or the ordering is incorrect.
"##)

register_diagnostics!(
    E0002,
    E0003,
    E0004,
    E0005,
    E0006,
    E0007,
    E0008,
    E0009,
    E0010,
    E0011,
    E0012,
    E0013,
    E0014,
    E0015,
    E0016,
    E0017,
    E0018,
    E0019,
    E0020,
    E0022,
    E0109,
    E0110,
    E0133,
    E0134,
    E0135,
    E0136,
    E0137,
    E0138,
    E0139,
    E0140,
    E0152,
    E0153,
    E0157,
    E0158,
    E0161,
    E0162,
    E0165,
    E0166,
    E0167,
    E0168,
    E0169,
    E0170,
    E0171,
    E0172,
    E0173,
    E0174,
    E0177,
    E0178
)
<|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/. */

//#![feature(mpsc_select)]

//! A GPU based Webrender.
//!
//! It serves as an experimental render backend for [Servo](https://servo.org/),
//! but it can also be used as such in a standalone application.
//!
//! # External dependencies
//! Webrender currently depends on [FreeType](https://www.freetype.org/)
//!
//! # Api Structure
//! The main entry point to webrender is the `webrender::renderer::Renderer`.
//!
//! By calling `Renderer::new(...)` you get a `Renderer`, as well as a `RenderApiSender`.
//! Your `Renderer` is responsible to render the previously processed frames onto the screen.
//!
//! By calling `yourRenderApiSenderInstance.create_api()`, you'll get a `RenderApi` instance,
//! which is responsible for the processing of new frames. A worker thread is used internally to
//! untie the workload from the application thread and therefore be able
//! to make better use of multicore systems.
//!
//! What is referred to as a `frame`, is the current geometry on the screen.
//! A new Frame is created by calling [`set_root_display_list()`][newframe] on the `RenderApi`.
//! When the geometry is processed, the application will be informed via a `RenderNotifier`,
//! a callback which you employ with [set_render_notifier][notifier] on the `Renderer`
//! More information about [stacking contexts][stacking_contexts].
//!
//! `set_root_display_list()` also needs to be supplied with `BuiltDisplayList`s.
//! These are obtained by finalizing a `DisplayListBuilder`. These are used to draw your geometry.
//! But it doesn't only contain trivial geometry, it can also store another StackingContext, as
//! they're nestable.
//!
//! Remember to insert the DisplayListId into the StackingContext as well, as they'll be referenced
//! from there. An Id for your DisplayList can be obtained by calling
//! `yourRenderApiInstance.next_display_list_id();`
//!
//! [stacking_contexts]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
//! [newframe]: ../webrender_traits/struct.RenderApi.html#method.set_root_display_list
//! [notifier]: renderer/struct.Renderer.html#method.set_render_notifier

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;

mod batch_builder;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;
mod debug_font_data;
mod debug_render;
mod device;
mod frame;
mod frame_builder;
mod freelist;
mod geometry;
mod gpu_store;
mod internal_types;
mod mask_cache;
mod prim_store;
mod profiler;
mod record;
mod render_backend;
mod render_task;
mod resource_cache;
mod scene;
mod spring;
mod texture_cache;
mod tiling;
mod util;

#[cfg(feature = "webgl")]
mod webgl_types;

#[cfg(not(feature = "webgl"))]
#[path = "webgl_stubs.rs"]
mod webgl_types;

mod shader_source {
    include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
}

pub use record::{ApiRecordingReceiver, BinaryRecorder, WEBRENDER_RECORDING_HEADER};

mod platform {
    #[cfg(target_os="macos")]
    pub use platform::macos::font;
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub use platform::unix::font;
    #[cfg(target_os = "windows")]
    pub use platform::windows::font;

    #[cfg(target_os="macos")]
    pub mod macos {
        pub mod font;
    }
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub mod unix {
        pub mod font;
    }
    #[cfg(target_os = "windows")]
    pub mod windows {
        pub mod font;
    }
}

pub mod renderer;

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

#[cfg(all(unix, not(target_os="macos")))]
extern crate freetype;

#[cfg(target_os = "windows")]
extern crate dwrote;

extern crate app_units;
extern crate bincode;
extern crate euclid;
extern crate fnv;
extern crate gleam;
extern crate num_traits;
//extern crate notify;
extern crate time;
extern crate webrender_traits;
#[cfg(feature = "webgl")]
extern crate offscreen_gl_context;
extern crate byteorder;
extern crate threadpool;

#[cfg(any(target_os="macos", target_os="windows"))]
extern crate gamma_lut;

pub use renderer::{ExternalImage, ExternalImageSource, ExternalImageHandler};
pub use renderer::{Renderer, RendererOptions};
<commit_msg>docs: Remove reference to DisplayListId.<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/. */

//#![feature(mpsc_select)]

//! A GPU based Webrender.
//!
//! It serves as an experimental render backend for [Servo](https://servo.org/),
//! but it can also be used as such in a standalone application.
//!
//! # External dependencies
//! Webrender currently depends on [FreeType](https://www.freetype.org/)
//!
//! # Api Structure
//! The main entry point to webrender is the `webrender::renderer::Renderer`.
//!
//! By calling `Renderer::new(...)` you get a `Renderer`, as well as a `RenderApiSender`.
//! Your `Renderer` is responsible to render the previously processed frames onto the screen.
//!
//! By calling `yourRenderApiSenderInstance.create_api()`, you'll get a `RenderApi` instance,
//! which is responsible for the processing of new frames. A worker thread is used internally to
//! untie the workload from the application thread and therefore be able
//! to make better use of multicore systems.
//!
//! What is referred to as a `frame`, is the current geometry on the screen.
//! A new Frame is created by calling [`set_root_display_list()`][newframe] on the `RenderApi`.
//! When the geometry is processed, the application will be informed via a `RenderNotifier`,
//! a callback which you employ with [set_render_notifier][notifier] on the `Renderer`
//! More information about [stacking contexts][stacking_contexts].
//!
//! `set_root_display_list()` also needs to be supplied with `BuiltDisplayList`s.
//! These are obtained by finalizing a `DisplayListBuilder`. These are used to draw your geometry.
//! But it doesn't only contain trivial geometry, it can also store another StackingContext, as
//! they're nestable.
//!
//! [stacking_contexts]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
//! [newframe]: ../webrender_traits/struct.RenderApi.html#method.set_root_display_list
//! [notifier]: renderer/struct.Renderer.html#method.set_render_notifier

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;

mod batch_builder;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;
mod debug_font_data;
mod debug_render;
mod device;
mod frame;
mod frame_builder;
mod freelist;
mod geometry;
mod gpu_store;
mod internal_types;
mod mask_cache;
mod prim_store;
mod profiler;
mod record;
mod render_backend;
mod render_task;
mod resource_cache;
mod scene;
mod spring;
mod texture_cache;
mod tiling;
mod util;

#[cfg(feature = "webgl")]
mod webgl_types;

#[cfg(not(feature = "webgl"))]
#[path = "webgl_stubs.rs"]
mod webgl_types;

mod shader_source {
    include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
}

pub use record::{ApiRecordingReceiver, BinaryRecorder, WEBRENDER_RECORDING_HEADER};

mod platform {
    #[cfg(target_os="macos")]
    pub use platform::macos::font;
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub use platform::unix::font;
    #[cfg(target_os = "windows")]
    pub use platform::windows::font;

    #[cfg(target_os="macos")]
    pub mod macos {
        pub mod font;
    }
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub mod unix {
        pub mod font;
    }
    #[cfg(target_os = "windows")]
    pub mod windows {
        pub mod font;
    }
}

pub mod renderer;

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

#[cfg(all(unix, not(target_os="macos")))]
extern crate freetype;

#[cfg(target_os = "windows")]
extern crate dwrote;

extern crate app_units;
extern crate bincode;
extern crate euclid;
extern crate fnv;
extern crate gleam;
extern crate num_traits;
//extern crate notify;
extern crate time;
extern crate webrender_traits;
#[cfg(feature = "webgl")]
extern crate offscreen_gl_context;
extern crate byteorder;
extern crate threadpool;

#[cfg(any(target_os="macos", target_os="windows"))]
extern crate gamma_lut;

pub use renderer::{ExternalImage, ExternalImageSource, ExternalImageHandler};
pub use renderer::{Renderer, RendererOptions};
<|endoftext|>


<commit_before>use std;
use std::ops::Range;
use std::collections::HashSet;

use rand;
use rand::Rng;

use tcod;
use tcod::console::Console;
use tcod::Color;

use traits::{Position, Renderable};
use units::{Unit, UnitTypeLists};

use point::Point;
use rectangle::Rectangle;

use SCREEN_WIDTH;
use SCREEN_HEIGHT;

const MAP_MIN_WIDTH: u8 = SCREEN_WIDTH;
const MAP_MIN_HEIGHT: u8 = SCREEN_HEIGHT;
pub const MAP_MAX_WIDTH: u8 = std::u8::MAX;
pub const MAP_MAX_HEIGHT: u8 = std::u8::MAX;

const ROOM_MAX_MONSTERS: u8 = 3;
// Values for I/N chance of generating monsters for a room.
const ROOM_CHANCE_OF_MONSTERS_I: u32 = 2;
const ROOM_CHANCE_OF_MONSTERS_N: u32 = 5;
const ROOM_MAX_SIZE: u8 = 10;
const ROOM_MIN_SIZE: u8 = 6;
// This value determines the maximum number of rooms for a given map size.
// This was calculated by the previous map size (80 x 45) divided by the
// previous max room count of 30.
// This should provide a similar room densiter for each map.
const ROOM_PER_TILE: u8 = 120;

const ERR_MSG_TUNNEL: &str = "Failed to create tunnel.";
const ERR_MSG_ROOM: &str = "Failed to create room.";
const ERR_MSG_ROOM_CMP: &str = "Error comparing rooms.";

#[derive(Debug, Copy, Clone)]
pub enum CanMoveResponse {
    Open,
    Scenery,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TileType {
    Floor,
    Wall,
}

impl TileType {
    fn get_color_not_visible(self) -> Color {
        match self {
            TileType::Floor => Color::new(50, 50, 150),
            TileType::Wall => Color::new(0, 0, 100),
        }
    }

    fn get_color_visible(self) -> Color {
        match self {
            TileType::Floor => Color::new(200, 180, 50),
            TileType::Wall => Color::new(130, 110, 50),
        }
    }

    fn get_glyph(self) -> char {
        match self {
            TileType::Floor => '.',
            TileType::Wall => '#',
        }
    }

    pub fn blocks_move(self) -> bool {
        match self {
            TileType::Floor => false,
            TileType::Wall => true,
        }
    }

    pub fn blocks_sight(self) -> bool {
        match self {
            TileType::Floor => false,
            TileType::Wall => true,
        }
    }
}

#[derive(Debug)]
pub struct Tile {
    position: Point<i16>,
    tile_type: TileType,
    is_explored: bool,
    is_visible: bool,
}

impl Position for Tile {
    fn get_x(&self) -> i16 {
        self.position.x
    }

    fn get_y(&self) -> i16 {
        self.position.y
    }
}

impl Renderable for Tile {
    fn get_color(&self) -> Color {
        if !self.is_explored {
            tcod::colors::BLACK
        } else {
            match self.is_visible {
                true => self.tile_type.get_color_visible(),
                false => self.tile_type.get_color_not_visible(),
            }
        }
    }
    fn get_glyph(&self) -> char {
        self.tile_type.get_glyph()
    }
}

impl Tile {
    pub fn new(pos: Point<i16>, tile_type: TileType) -> Tile {
        Tile{
            position: pos,
            tile_type: tile_type,
            is_explored: false,
            is_visible: false,
        }
    }
}

pub struct Map {
    width: u8,
    height: u8,
    tile_map: Vec<Tile>,
    fov_map: tcod::map::Map,
}

// Init and building.
impl Map {
    pub fn init<'a>(unit_types: &'a UnitTypeLists) -> (Map, Vec<Unit<'a>>, Point<i16>) {
        let mut rng = rand::thread_rng();

        let map_width = rng.gen_range(MAP_MIN_WIDTH, MAP_MAX_WIDTH);
        let map_height = rng.gen_range(MAP_MIN_HEIGHT, MAP_MAX_HEIGHT);

        let mut map = vec![];
        for y in 0..map_height {
            for x in 0..map_width {
                map.push( Tile::new(Point{x: x as i16, y: y as i16}, TileType::Wall) );
            }
        }

        let mut map = Map {
            width: map_width,
            height: map_height,
            tile_map: map,
            fov_map: tcod::map::Map::new(map_width as i32, map_height as i32),
        };

        let mut npcs = vec![];

        // Set all tiles to be not walkable, not transparent.
        // We'll be setting these in the build_rooms and build_coridoors methods.
        map.fov_map.clear(false, false);

        let (rooms, player_start) = map.build_rooms(&mut rng);
        map.build_coridoors(&rooms, &mut rng);

        for room in rooms {
            if rng.gen_range(0, ROOM_CHANCE_OF_MONSTERS_N) < ROOM_CHANCE_OF_MONSTERS_I {
                map.place_objects(&room, &unit_types, &mut npcs, &mut rng);
            }
        }

        (map, npcs, player_start)
    }

    fn place_objects<'a>(&mut self, room: &Rectangle, units: &'a UnitTypeLists, npc_list: &mut Vec<Unit<'a>>, rng: &mut rand::ThreadRng) {
        let max_monsters = rng.gen_range(0, ROOM_MAX_MONSTERS);

        for _ in 0..max_monsters {
            let position = room.get_random_position(rng);
            let monster_type = units.get_random_type(rng);

            let monster = Unit::new(position, monster_type);
            npc_list.push(monster);
        }
    }

    fn build_rooms(&mut self, rng: &mut rand::ThreadRng) -> (Vec<Rectangle>, Point<i16>) {
        let mut rooms = vec![];
        let mut player_start = Point{x:0, y:0};

        // Casts are to avoid overflow.
        let max_rooms = self.width as u16 * self.height as u16 / ROOM_PER_TILE as u16;

        for _ in 0..max_rooms {
            let width = rng.gen_range(ROOM_MIN_SIZE, ROOM_MAX_SIZE);
            let height = rng.gen_range(ROOM_MIN_SIZE, ROOM_MAX_SIZE);

            let room = Rectangle::new(
                Point {
                    x: rng.gen_range(0, self.width as i16 - width as i16 - 1),
                    y: rng.gen_range(0, self.height as i16 - height as i16 - 1)
                },
                (width, height)
            );

            if !rooms.iter().any(|r: &Rectangle| r.is_intersecting(&room)) {
                self.create_room(&room).expect(ERR_MSG_ROOM);

                if rooms.len() == 0 {
                    player_start = room.centre();
                }

                rooms.push(room);
            }
        }

        (rooms, player_start)
    }

    fn build_coridoors(&mut self, rooms: &Vec<Rectangle>, rng: &mut rand::ThreadRng) {
        let mut sorted_rooms: Vec<_> = rooms.iter().map(|r| r).collect();
        let mut connected_rooms = HashSet::new();

        for room in rooms {
            sorted_rooms.sort_by(|a,b| (room.centre() - a.centre()).sqr_radius().partial_cmp(&(room.centre() - b.centre()).sqr_radius()).expect(ERR_MSG_ROOM_CMP) );

            for next in sorted_rooms.iter().skip(1).take(3) {
                if connected_rooms.contains(&(*next, room)) {
                    continue;
                }

                connected_rooms.insert((room, *next));

                let r1_centre = room.centre();
                let r2_centre = next.centre();

                // Decide whether to first tunnel horizontally or vertically.
                if rng.gen_weighted_bool(2) {
                    // Horizontal
                    self.create_h_tunnel(r1_centre.x..r2_centre.x, r1_centre.y).expect(ERR_MSG_TUNNEL);
                    self.create_v_tunnel(r2_centre.x, r1_centre.y..r2_centre.y).expect(ERR_MSG_TUNNEL);
                } else {
                    // Vertical
                    self.create_v_tunnel(r1_centre.x, r1_centre.y..r2_centre.y).expect(ERR_MSG_TUNNEL);
                    self.create_h_tunnel(r1_centre.x..r2_centre.x, r2_centre.y).expect(ERR_MSG_TUNNEL);
                }
            }
        }
    }

    fn create_v_tunnel(&mut self, x: i16, y_r: Range<i16>) -> Result<(),()> {
        // Need to handle the case where start > end.
        // I decided to do it here to make it easier to call the function.
        // Because this is a half-open range, we need to adjust the start
        // and end to account for that.
        let y_r = if y_r.start > y_r.end {
            y_r.end+1 .. y_r.start+1
        } else {
            y_r
        };

        for y in y_r {
            let pos = Point{x:x, y:y};
            self.set_tile_type(pos, TileType::Floor)?;
            self.fov_map.set(x as i32, y as i32, true, true);
        }

        Ok(())
    }

    fn create_h_tunnel(&mut self, x_r: Range<i16>, y: i16) -> Result<(),()> {
        // Need to handle the case where start > end.
        // I decided to do it here to make it easier to call the function.
        // Because this is a half-open range, we need to adjust the start
        // and end to account for that.
        let x_r = if x_r.start > x_r.end {
            x_r.end+1 .. x_r.start+1
        } else {
            x_r
        };

        for x in x_r {
            let pos = Point{x:x, y:y};
            self.set_tile_type(pos, TileType::Floor)?;
            self.fov_map.set(x as i32, y as i32, true, true);
        }

        Ok(())
    }

    fn create_room(&mut self, rect: &Rectangle) -> Result<(),()> {
        for y in (rect.top_left.y+1)..rect.bottom_right.y {
            for x in (rect.top_left.x+1)..rect.bottom_right.x {
                let pos = Point{x:x, y:y};
                self.set_tile_type(pos, TileType::Floor)?;
                self.fov_map.set(x as i32, y as i32, true, true);
            }
        }

        Ok(())
    }
}

// Rendering
impl Map {
    pub fn render_map<T: Console>(&self, cons: &mut T) {
        for tile in self.tile_map.iter() {
            tile.render(cons);
        }
    }
}

// Queries
impl Map {
    pub fn point_in_map(&self, Point{x,y}: Point<i16>) -> bool {
        x >= 0 && x < self.width as i16 && y >= 0 && y < self.height as i16
    }

    pub fn get_tile_type(&self, pos: Point<i16>) -> Result<TileType,()> {
        if !self.point_in_map(pos) {
            Err(())
        } else {
            let Point{x, y} = pos;
            Ok(self.tile_map[y as usize * self.width as usize + x as usize].tile_type)
        }
    }

    pub fn can_move_to(&self, pos: Point<i16>) -> CanMoveResponse {
        match self.get_tile_type(pos) {
            Ok(tile) if tile.blocks_move() => CanMoveResponse::Scenery,
            _ => CanMoveResponse::Open
        }
    }

    pub fn get_map_size(&self) -> (u8, u8) {
        (self.width, self.height)
    }

    pub fn point_in_fov(&self, Point{x,y}: Point<i16>) -> bool {
        self.fov_map.is_in_fov(x as i32, y as i32)
    }
}

// Updating
impl Map {
    pub fn update_fov(&mut self, Point{x, y}: Point<i16>, light_radius: u8) {
        self.fov_map.compute_fov(x as i32, y as i32, light_radius as i32, true, tcod::map::FovAlgorithm::Permissive0);

        // I've opted to update the tile map here, because it doesn't make sense that
        // a function for rendering should need to mutate the object.
        // It does make this function more expensive to run, but it won't be run
        // too frequently.
        for tile in self.tile_map.iter_mut() {
            tile.is_visible = self.fov_map.is_in_fov(tile.get_x() as i32, tile.get_y() as i32);

            if tile.is_visible {
                tile.is_explored = true;
            }
        }
    }

    fn set_tile_type(&mut self, pos: Point<i16>, new_tile: TileType) -> Result<(),()> {
        if !self.point_in_map(pos) {
            Err(())
        } else {
            let Point{x,y} = pos;
            self.tile_map[y as usize * self.width as usize + x as usize].tile_type = new_tile;

            Ok(())
        }
    }
}<commit_msg>Made CanMoveResponse Eq, PartialEq.<commit_after>use std;
use std::ops::Range;
use std::collections::HashSet;

use rand;
use rand::Rng;

use tcod;
use tcod::console::Console;
use tcod::Color;

use traits::{Position, Renderable};
use units::{Unit, UnitTypeLists};

use point::Point;
use rectangle::Rectangle;

use SCREEN_WIDTH;
use SCREEN_HEIGHT;

const MAP_MIN_WIDTH: u8 = SCREEN_WIDTH;
const MAP_MIN_HEIGHT: u8 = SCREEN_HEIGHT;
pub const MAP_MAX_WIDTH: u8 = std::u8::MAX;
pub const MAP_MAX_HEIGHT: u8 = std::u8::MAX;

const ROOM_MAX_MONSTERS: u8 = 3;
// Values for I/N chance of generating monsters for a room.
const ROOM_CHANCE_OF_MONSTERS_I: u32 = 2;
const ROOM_CHANCE_OF_MONSTERS_N: u32 = 5;
const ROOM_MAX_SIZE: u8 = 10;
const ROOM_MIN_SIZE: u8 = 6;
// This value determines the maximum number of rooms for a given map size.
// This was calculated by the previous map size (80 x 45) divided by the
// previous max room count of 30.
// This should provide a similar room densiter for each map.
const ROOM_PER_TILE: u8 = 120;

const ERR_MSG_TUNNEL: &str = "Failed to create tunnel.";
const ERR_MSG_ROOM: &str = "Failed to create room.";
const ERR_MSG_ROOM_CMP: &str = "Error comparing rooms.";

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum CanMoveResponse {
    Open,
    Scenery,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TileType {
    Floor,
    Wall,
}

impl TileType {
    fn get_color_not_visible(self) -> Color {
        match self {
            TileType::Floor => Color::new(50, 50, 150),
            TileType::Wall => Color::new(0, 0, 100),
        }
    }

    fn get_color_visible(self) -> Color {
        match self {
            TileType::Floor => Color::new(200, 180, 50),
            TileType::Wall => Color::new(130, 110, 50),
        }
    }

    fn get_glyph(self) -> char {
        match self {
            TileType::Floor => '.',
            TileType::Wall => '#',
        }
    }

    pub fn blocks_move(self) -> bool {
        match self {
            TileType::Floor => false,
            TileType::Wall => true,
        }
    }

    pub fn blocks_sight(self) -> bool {
        match self {
            TileType::Floor => false,
            TileType::Wall => true,
        }
    }
}

#[derive(Debug)]
pub struct Tile {
    position: Point<i16>,
    tile_type: TileType,
    is_explored: bool,
    is_visible: bool,
}

impl Position for Tile {
    fn get_x(&self) -> i16 {
        self.position.x
    }

    fn get_y(&self) -> i16 {
        self.position.y
    }
}

impl Renderable for Tile {
    fn get_color(&self) -> Color {
        if !self.is_explored {
            tcod::colors::BLACK
        } else {
            match self.is_visible {
                true => self.tile_type.get_color_visible(),
                false => self.tile_type.get_color_not_visible(),
            }
        }
    }
    fn get_glyph(&self) -> char {
        self.tile_type.get_glyph()
    }
}

impl Tile {
    pub fn new(pos: Point<i16>, tile_type: TileType) -> Tile {
        Tile{
            position: pos,
            tile_type: tile_type,
            is_explored: false,
            is_visible: false,
        }
    }
}

pub struct Map {
    width: u8,
    height: u8,
    tile_map: Vec<Tile>,
    fov_map: tcod::map::Map,
}

// Init and building.
impl Map {
    pub fn init<'a>(unit_types: &'a UnitTypeLists) -> (Map, Vec<Unit<'a>>, Point<i16>) {
        let mut rng = rand::thread_rng();

        let map_width = rng.gen_range(MAP_MIN_WIDTH, MAP_MAX_WIDTH);
        let map_height = rng.gen_range(MAP_MIN_HEIGHT, MAP_MAX_HEIGHT);

        let mut map = vec![];
        for y in 0..map_height {
            for x in 0..map_width {
                map.push( Tile::new(Point{x: x as i16, y: y as i16}, TileType::Wall) );
            }
        }

        let mut map = Map {
            width: map_width,
            height: map_height,
            tile_map: map,
            fov_map: tcod::map::Map::new(map_width as i32, map_height as i32),
        };

        let mut npcs = vec![];

        // Set all tiles to be not walkable, not transparent.
        // We'll be setting these in the build_rooms and build_coridoors methods.
        map.fov_map.clear(false, false);

        let (rooms, player_start) = map.build_rooms(&mut rng);
        map.build_coridoors(&rooms, &mut rng);

        for room in rooms {
            if rng.gen_range(0, ROOM_CHANCE_OF_MONSTERS_N) < ROOM_CHANCE_OF_MONSTERS_I {
                map.place_objects(&room, &unit_types, &mut npcs, &mut rng);
            }
        }

        (map, npcs, player_start)
    }

    fn place_objects<'a>(&mut self, room: &Rectangle, units: &'a UnitTypeLists, npc_list: &mut Vec<Unit<'a>>, rng: &mut rand::ThreadRng) {
        let max_monsters = rng.gen_range(0, ROOM_MAX_MONSTERS);

        for _ in 0..max_monsters {
            let position = room.get_random_position(rng);
            let monster_type = units.get_random_type(rng);

            let monster = Unit::new(position, monster_type);
            npc_list.push(monster);
        }
    }

    fn build_rooms(&mut self, rng: &mut rand::ThreadRng) -> (Vec<Rectangle>, Point<i16>) {
        let mut rooms = vec![];
        let mut player_start = Point{x:0, y:0};

        // Casts are to avoid overflow.
        let max_rooms = self.width as u16 * self.height as u16 / ROOM_PER_TILE as u16;

        for _ in 0..max_rooms {
            let width = rng.gen_range(ROOM_MIN_SIZE, ROOM_MAX_SIZE);
            let height = rng.gen_range(ROOM_MIN_SIZE, ROOM_MAX_SIZE);

            let room = Rectangle::new(
                Point {
                    x: rng.gen_range(0, self.width as i16 - width as i16 - 1),
                    y: rng.gen_range(0, self.height as i16 - height as i16 - 1)
                },
                (width, height)
            );

            if !rooms.iter().any(|r: &Rectangle| r.is_intersecting(&room)) {
                self.create_room(&room).expect(ERR_MSG_ROOM);

                if rooms.len() == 0 {
                    player_start = room.centre();
                }

                rooms.push(room);
            }
        }

        (rooms, player_start)
    }

    fn build_coridoors(&mut self, rooms: &Vec<Rectangle>, rng: &mut rand::ThreadRng) {
        let mut sorted_rooms: Vec<_> = rooms.iter().map(|r| r).collect();
        let mut connected_rooms = HashSet::new();

        for room in rooms {
            sorted_rooms.sort_by(|a,b| (room.centre() - a.centre()).sqr_radius().partial_cmp(&(room.centre() - b.centre()).sqr_radius()).expect(ERR_MSG_ROOM_CMP) );

            for next in sorted_rooms.iter().skip(1).take(3) {
                if connected_rooms.contains(&(*next, room)) {
                    continue;
                }

                connected_rooms.insert((room, *next));

                let r1_centre = room.centre();
                let r2_centre = next.centre();

                // Decide whether to first tunnel horizontally or vertically.
                if rng.gen_weighted_bool(2) {
                    // Horizontal
                    self.create_h_tunnel(r1_centre.x..r2_centre.x, r1_centre.y).expect(ERR_MSG_TUNNEL);
                    self.create_v_tunnel(r2_centre.x, r1_centre.y..r2_centre.y).expect(ERR_MSG_TUNNEL);
                } else {
                    // Vertical
                    self.create_v_tunnel(r1_centre.x, r1_centre.y..r2_centre.y).expect(ERR_MSG_TUNNEL);
                    self.create_h_tunnel(r1_centre.x..r2_centre.x, r2_centre.y).expect(ERR_MSG_TUNNEL);
                }
            }
        }
    }

    fn create_v_tunnel(&mut self, x: i16, y_r: Range<i16>) -> Result<(),()> {
        // Need to handle the case where start > end.
        // I decided to do it here to make it easier to call the function.
        // Because this is a half-open range, we need to adjust the start
        // and end to account for that.
        let y_r = if y_r.start > y_r.end {
            y_r.end+1 .. y_r.start+1
        } else {
            y_r
        };

        for y in y_r {
            let pos = Point{x:x, y:y};
            self.set_tile_type(pos, TileType::Floor)?;
            self.fov_map.set(x as i32, y as i32, true, true);
        }

        Ok(())
    }

    fn create_h_tunnel(&mut self, x_r: Range<i16>, y: i16) -> Result<(),()> {
        // Need to handle the case where start > end.
        // I decided to do it here to make it easier to call the function.
        // Because this is a half-open range, we need to adjust the start
        // and end to account for that.
        let x_r = if x_r.start > x_r.end {
            x_r.end+1 .. x_r.start+1
        } else {
            x_r
        };

        for x in x_r {
            let pos = Point{x:x, y:y};
            self.set_tile_type(pos, TileType::Floor)?;
            self.fov_map.set(x as i32, y as i32, true, true);
        }

        Ok(())
    }

    fn create_room(&mut self, rect: &Rectangle) -> Result<(),()> {
        for y in (rect.top_left.y+1)..rect.bottom_right.y {
            for x in (rect.top_left.x+1)..rect.bottom_right.x {
                let pos = Point{x:x, y:y};
                self.set_tile_type(pos, TileType::Floor)?;
                self.fov_map.set(x as i32, y as i32, true, true);
            }
        }

        Ok(())
    }
}

// Rendering
impl Map {
    pub fn render_map<T: Console>(&self, cons: &mut T) {
        for tile in self.tile_map.iter() {
            tile.render(cons);
        }
    }
}

// Queries
impl Map {
    pub fn point_in_map(&self, Point{x,y}: Point<i16>) -> bool {
        x >= 0 && x < self.width as i16 && y >= 0 && y < self.height as i16
    }

    pub fn get_tile_type(&self, pos: Point<i16>) -> Result<TileType,()> {
        if !self.point_in_map(pos) {
            Err(())
        } else {
            let Point{x, y} = pos;
            Ok(self.tile_map[y as usize * self.width as usize + x as usize].tile_type)
        }
    }

    pub fn can_move_to(&self, pos: Point<i16>) -> CanMoveResponse {
        match self.get_tile_type(pos) {
            Ok(tile) if tile.blocks_move() => CanMoveResponse::Scenery,
            _ => CanMoveResponse::Open
        }
    }

    pub fn get_map_size(&self) -> (u8, u8) {
        (self.width, self.height)
    }

    pub fn point_in_fov(&self, Point{x,y}: Point<i16>) -> bool {
        self.fov_map.is_in_fov(x as i32, y as i32)
    }
}

// Updating
impl Map {
    pub fn update_fov(&mut self, Point{x, y}: Point<i16>, light_radius: u8) {
        self.fov_map.compute_fov(x as i32, y as i32, light_radius as i32, true, tcod::map::FovAlgorithm::Permissive0);

        // I've opted to update the tile map here, because it doesn't make sense that
        // a function for rendering should need to mutate the object.
        // It does make this function more expensive to run, but it won't be run
        // too frequently.
        for tile in self.tile_map.iter_mut() {
            tile.is_visible = self.fov_map.is_in_fov(tile.get_x() as i32, tile.get_y() as i32);

            if tile.is_visible {
                tile.is_explored = true;
            }
        }
    }

    fn set_tile_type(&mut self, pos: Point<i16>, new_tile: TileType) -> Result<(),()> {
        if !self.point_in_map(pos) {
            Err(())
        } else {
            let Point{x,y} = pos;
            self.tile_map[y as usize * self.width as usize + x as usize].tile_type = new_tile;

            Ok(())
        }
    }
}<|endoftext|>


<commit_before>use std::io::File;
use std::fmt;
use std::mem;
use std::os;

#[repr(C)]
struct Complex {
    re: f32,
    im: f32,
}

#[link(name = "m")]
extern {
    fn csqrtf(z: Complex) -> Complex;
}

fn pointer_size() -> uint {
    let tmp = 0u8;
    let boxed = box tmp;
    mem::size_of_val(&boxed)
}

fn main() {
    let args = os::args();
    if args.len() != 2 {
        println!("usage: read_blend_file /path/to/file.blend");
    } else {
        let slice: &str = args[1].as_slice();
        println!("open \"{}\" ...", slice);
        {
            // read 7 bytes from the Blender file
            let path = Path::new(slice);
            let display = path.display();
            let mut file = match File::open(&path) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(file) => file,
            };
            let mut buf = [0u8, ..7];
            match file.read(buf) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(_) => (),
            }
            // pack those 7 bytes into a string ...
            let mut string = String::new();
            for n in range(0u, 7) {
                string.push(buf[n] as char);
            }
            // ... to be able to compare them
            if string == String::from_str("BLENDER") {
                println!("INFO: a Blender file.");
                println!("size of pointer in bytes: {}", pointer_size());
            } else {
                println!("ERROR: not a Blender file.");
            }
        } // file gets closed here
        // code below is temporary
        let z = Complex { re: -1.0, im: 0.0 };
        let z_sqrt = unsafe {
            csqrtf(z)
        };
        println!("the square root of {} is {}", z, z_sqrt);
    }
}

impl fmt::Show for Complex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < 0. {
            write!(f, "{}-{}i", self.re, -self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}
<commit_msg>Read 12 chars instead of 7 but still compare the first 7 against "BLENDER".<commit_after>use std::io::File;
use std::fmt;
use std::mem;
use std::os;

#[repr(C)]
struct Complex {
    re: f32,
    im: f32,
}

#[link(name = "m")]
extern {
    fn csqrtf(z: Complex) -> Complex;
}

fn pointer_size() -> uint {
    let tmp = 0u8;
    let boxed = box tmp;
    mem::size_of_val(&boxed)
}

fn main() {
    let args = os::args();
    if args.len() != 2 {
        println!("usage: read_blend_file /path/to/file.blend");
    } else {
        let slice: &str = args[1].as_slice();
        println!("open \"{}\" ...", slice);
        {
            // read 12 bytes from the Blender file
            let path = Path::new(slice);
            let display = path.display();
            let mut file = match File::open(&path) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(file) => file,
            };
            let mut buf = [0u8, ..12];
            match file.read(buf) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(_) => (),
            }
            // pack those 12 bytes into a string ...
            let mut header = String::new();
            for n in range(0u, 12) {
                header.push(buf[n] as char);
            }
            // ... to be able to compare them
            let slice = header.as_slice();
            let blender: &str = slice.slice(0, 7); // first 7 chars
            if blender == "BLENDER" {
                println!("INFO: a Blender file.");
                println!("size of pointer in bytes: {}", pointer_size());
                println!("Header (12 chars): {}", header);
            } else {
                println!("ERROR: not a Blender file.");
            }
        } // file gets closed here
        // code below is temporary
        let z = Complex { re: -1.0, im: 0.0 };
        let z_sqrt = unsafe {
            csqrtf(z)
        };
        println!("the square root of {} is {}", z, z_sqrt);
    }
}

impl fmt::Show for Complex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < 0. {
            write!(f, "{}-{}i", self.re, -self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}
<|endoftext|>


<commit_before>//! Code for generating action code.
//!
//! From the outside, action fns have one of two forms. If they take
//! symbols as input, e.g. from a production like `X = Y Z => ...`
//! (which takes Y and Z as input), they have this form:
//!
//! ```
//! fn __action17<
//!     'input,                       // user-declared type parameters (*)
//! >(
//!     input: &'input str,           // user-declared parameters
//!     __0: (usize, usize, usize),   // symbols being reduced, if any
//!     ...
//!     __N: (usize, Foo, usize),     // each has a type (L, T, L)
//! ) -> Box<Expr<'input>>
//! ```
//!
//! Otherwise, they have this form:
//!
//! ```
//! fn __action17<
//!     'input,                       // user-declared type parameters (*)
//! >(
//!     input: &'input str,           // user-declared parameters
//!    __lookbehind: &usize,          // value for @R -- "end of previous token"
//!    __lookahead: &usize,           // value for @L -- "start of next token"
//! ) -> Box<Expr<'input>>
//! ```
//!
//! * -- in this case, those "user-declared" parameters are inserted by
//! the "internal tokenizer".

use grammar::repr as r;
use rust::RustWrite;
use std::io::{self, Write};

pub fn emit_action_code<W: Write>(grammar: &r::Grammar, rust: &mut RustWrite<W>) -> io::Result<()> {
    for (i, defn) in grammar.action_fn_defns.iter().enumerate() {
        rust!(rust, "");

        // we always thread the parameters through to the action code,
        // even if they are not used, and hence we need to disable the
        // unused variables lint, which otherwise gets very excited.
        if !grammar.parameters.is_empty() {
            rust!(rust, "#[allow(unused_variables)]");
        }

        match defn.kind {
            r::ActionFnDefnKind::User(ref data) => {
                try!(emit_user_action_code(grammar, rust, i, defn, data))
            }
            r::ActionFnDefnKind::Lookaround(ref variant) => {
                try!(emit_lookaround_action_code(grammar, rust, i, defn, variant))
            }
            r::ActionFnDefnKind::Inline(ref data) => {
                try!(emit_inline_action_code(grammar, rust, i, defn, data))
            }
        }
    }

    Ok(())
}

fn ret_type_string(grammar: &r::Grammar, defn: &r::ActionFnDefn) -> String {
    if defn.fallible {
        format!(
            "Result<{},{}lalrpop_util::ParseError<{},{},{}>>",
            defn.ret_type,
            grammar.prefix,
            grammar.types.terminal_loc_type(),
            grammar.types.terminal_token_type(),
            grammar.types.error_type()
        )
    } else {
        format!("{}", defn.ret_type)
    }
}

fn emit_user_action_code<W: Write>(
    grammar: &r::Grammar,
    rust: &mut RustWrite<W>,
    index: usize,
    defn: &r::ActionFnDefn,
    data: &r::UserActionFnDefn,
) -> io::Result<()> {
    let ret_type = ret_type_string(grammar, defn);

    // For each symbol to be reduced, we will receive
    // a (L, T, L) triple where the Ls are locations and
    // the T is the data. Ignore the locations and bind
    // the data to the name the user gave.
    let mut arguments: Vec<String> = data
        .arg_patterns
        .iter()
        .zip(
            data.arg_types
                .iter()
                .cloned()
                .map(|t| grammar.types.spanned_type(t)),
        )
        .map(|(p, t)| format!("(_, {}, _): {}", p, t))
        .collect();

    // If this is a reduce of an empty production, we will
    // automatically add position information in the form of
    // lookbehind/lookahead values. Otherwise, those values would be
    // determined from the arguments themselves.
    if data.arg_patterns.is_empty() {
        arguments.extend(vec![
            format!(
                "{}lookbehind: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
            format!(
                "{}lookahead: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
        ]);
    }

    try!(rust.write_fn_header(
        grammar,
        &r::Visibility::Priv,
        format!("{}action{}", grammar.prefix, index),
        vec![],
        None,
        arguments,
        ret_type,
        vec![]
    ));
    rust!(rust, "{{");
    rust!(rust, "{}", data.code);
    rust!(rust, "}}");
    Ok(())
}

fn emit_lookaround_action_code<W: Write>(
    grammar: &r::Grammar,
    rust: &mut RustWrite<W>,
    index: usize,
    _defn: &r::ActionFnDefn,
    data: &r::LookaroundActionFnDefn,
) -> io::Result<()> {
    try!(rust.write_fn_header(
        grammar,
        &r::Visibility::Priv,
        format!("{}action{}", grammar.prefix, index),
        vec![],
        None,
        vec![
            format!(
                "{}lookbehind: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
            format!(
                "{}lookahead: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
        ],
        format!("{}", grammar.types.terminal_loc_type()),
        vec![]
    ));

    rust!(rust, "{{");
    match *data {
        r::LookaroundActionFnDefn::Lookahead => {
            // take the lookahead, if any; otherwise, we are
            // at EOF, so taker the lookbehind (end of last
            // pushed token); if that is missing too, then
            // supply default.
            rust!(rust, "{}lookahead.clone()", grammar.prefix);
        }
        r::LookaroundActionFnDefn::Lookbehind => {
            // take lookbehind or supply default
            rust!(rust, "{}lookbehind.clone()", grammar.prefix);
        }
    }
    rust!(rust, "}}");
    Ok(())
}

fn emit_inline_action_code<W: Write>(
    grammar: &r::Grammar,
    rust: &mut RustWrite<W>,
    index: usize,
    defn: &r::ActionFnDefn,
    data: &r::InlineActionFnDefn,
) -> io::Result<()> {
    let ret_type = ret_type_string(grammar, defn);

    let arg_types: Vec<_> = data
        .symbols
        .iter()
        .flat_map(|sym| match *sym {
            r::InlinedSymbol::Original(ref s) => vec![s.clone()],
            r::InlinedSymbol::Inlined(_, ref syms) => syms.clone(),
        })
        .map(|s| s.ty(&grammar.types))
        .collect();

    // this is the number of symbols we expect to be passed in; it is
    // distinct from data.symbols.len(), because sometimes we have
    // inlined actions with no input symbols
    let num_flat_args = arg_types.len();

    let mut arguments: Vec<_> = arg_types
        .iter()
        .map(|&t| grammar.types.spanned_type(t.clone()))
        .enumerate()
        .map(|(i, t)| format!("{}{}: {}", grammar.prefix, i, t))
        .collect();

    // If no symbols are being reduced, add in the
    // lookbehind/lookahead.
    if arguments.len() == 0 {
        arguments.extend(vec![
            format!(
                "{}lookbehind: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
            format!(
                "{}lookahead: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
        ]);
    }

    try!(rust.write_fn_header(
        grammar,
        &r::Visibility::Priv,
        format!("{}action{}", grammar.prefix, index),
        vec![],
        None,
        arguments,
        ret_type,
        vec![]
    ));
    rust!(rust, "{{");

    // For each inlined thing, compute the start/end locations.
    // Do this first so that none of the arguments have been moved
    // yet and we can easily access their locations.
    let mut arg_counter = 0;
    let mut temp_counter = 0;
    for symbol in &data.symbols {
        match *symbol {
            r::InlinedSymbol::Original(_) => {
                arg_counter += 1;
            }
            r::InlinedSymbol::Inlined(_, ref syms) => {
                if syms.len() > 0 {
                    // If we are reducing symbols, then start and end
                    // can be the start/end location of the first/last
                    // symbol respectively. Easy peezy.

                    rust!(
                        rust,
                        "let {}start{} = {}{}.0.clone();",
                        grammar.prefix,
                        temp_counter,
                        grammar.prefix,
                        arg_counter
                    );

                    let last_arg_index = arg_counter + syms.len() - 1;
                    rust!(
                        rust,
                        "let {}end{} = {}{}.2.clone();",
                        grammar.prefix,
                        temp_counter,
                        grammar.prefix,
                        last_arg_index
                    );
                } else {
                    // If we have no symbols, then `arg_counter`
                    // represents index of the first symbol after this
                    // inlined item (if any), and `arg_counter-1`
                    // represents index of the symbol before this
                    // item.

                    if arg_counter > 0 {
                        rust!(
                            rust,
                            "let {}start{} = {}{}.2.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix,
                            arg_counter - 1
                        );
                    } else if num_flat_args > 0 {
                        rust!(
                            rust,
                            "let {}start{} = {}{}.0.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix,
                            arg_counter
                        );
                    } else {
                        rust!(
                            rust,
                            "let {}start{} = {}lookbehind.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix
                        );
                    }

                    if arg_counter < num_flat_args {
                        rust!(
                            rust,
                            "let {}end{} = {}{}.0.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix,
                            arg_counter
                        );
                    } else if num_flat_args > 0 {
                        rust!(
                            rust,
                            "let {}end{} = {}{}.2.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix,
                            num_flat_args - 1
                        );
                    } else {
                        rust!(
                            rust,
                            "let {}end{} = {}lookahead.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix
                        );
                    }
                }

                temp_counter += 1;
                arg_counter += syms.len();
            }
        }
    }

    // Now create temporaries for the inlined things
    let mut arg_counter = 0;
    let mut temp_counter = 0;
    for symbol in &data.symbols {
        match *symbol {
            r::InlinedSymbol::Original(_) => {
                arg_counter += 1;
            }
            r::InlinedSymbol::Inlined(inlined_action, ref syms) => {
                // execute the inlined reduce action
                rust!(
                    rust,
                    "let {}temp{} = {}action{}::<",
                    grammar.prefix,
                    temp_counter,
                    grammar.prefix,
                    inlined_action.index()
                );
                for t in grammar.non_lifetime_type_parameters() {
                    rust!(rust, "{},", t);
                }
                rust!(rust, ">(");
                for parameter in &grammar.parameters {
                    rust!(rust, "{},", parameter.name);
                }
                for i in 0..syms.len() {
                    rust!(rust, "{}{},", grammar.prefix, arg_counter + i);
                }
                if syms.len() == 0 {
                    rust!(rust, "&{}start{},", grammar.prefix, temp_counter);
                    rust!(rust, "&{}end{},", grammar.prefix, temp_counter);
                }
                rust!(rust, ");");

                // wrap up the inlined value along with its span
                rust!(
                    rust,
                    "let {}temp{} = ({}start{}, {}temp{}, {}end{});",
                    grammar.prefix,
                    temp_counter,
                    grammar.prefix,
                    temp_counter,
                    grammar.prefix,
                    temp_counter,
                    grammar.prefix,
                    temp_counter
                );

                temp_counter += 1;
                arg_counter += syms.len();
            }
        }
    }
    rust!(rust, "{}action{}::<", grammar.prefix, data.action.index());
    for t in grammar.non_lifetime_type_parameters() {
        rust!(rust, "{},", t);
    }
    rust!(rust, ">(");
    for parameter in &grammar.parameters {
        rust!(rust, "{},", parameter.name);
    }
    let mut arg_counter = 0;
    let mut temp_counter = 0;
    for symbol in &data.symbols {
        match *symbol {
            r::InlinedSymbol::Original(_) => {
                rust!(rust, "{}{},", grammar.prefix, arg_counter);
                arg_counter += 1;
            }
            r::InlinedSymbol::Inlined(_, ref syms) => {
                rust!(rust, "{}temp{},", grammar.prefix, temp_counter);
                temp_counter += 1;
                arg_counter += syms.len();
            }
        }
    }
    assert!(data.symbols.len() > 0);
    rust!(rust, ")");

    rust!(rust, "}}");
    Ok(())
}
<commit_msg>Only insert annotations when type parameters exist<commit_after>//! Code for generating action code.
//!
//! From the outside, action fns have one of two forms. If they take
//! symbols as input, e.g. from a production like `X = Y Z => ...`
//! (which takes Y and Z as input), they have this form:
//!
//! ```
//! fn __action17<
//!     'input,                       // user-declared type parameters (*)
//! >(
//!     input: &'input str,           // user-declared parameters
//!     __0: (usize, usize, usize),   // symbols being reduced, if any
//!     ...
//!     __N: (usize, Foo, usize),     // each has a type (L, T, L)
//! ) -> Box<Expr<'input>>
//! ```
//!
//! Otherwise, they have this form:
//!
//! ```
//! fn __action17<
//!     'input,                       // user-declared type parameters (*)
//! >(
//!     input: &'input str,           // user-declared parameters
//!    __lookbehind: &usize,          // value for @R -- "end of previous token"
//!    __lookahead: &usize,           // value for @L -- "start of next token"
//! ) -> Box<Expr<'input>>
//! ```
//!
//! * -- in this case, those "user-declared" parameters are inserted by
//! the "internal tokenizer".

use grammar::repr as r;
use rust::RustWrite;
use std::io::{self, Write};

pub fn emit_action_code<W: Write>(grammar: &r::Grammar, rust: &mut RustWrite<W>) -> io::Result<()> {
    for (i, defn) in grammar.action_fn_defns.iter().enumerate() {
        rust!(rust, "");

        // we always thread the parameters through to the action code,
        // even if they are not used, and hence we need to disable the
        // unused variables lint, which otherwise gets very excited.
        if !grammar.parameters.is_empty() {
            rust!(rust, "#[allow(unused_variables)]");
        }

        match defn.kind {
            r::ActionFnDefnKind::User(ref data) => {
                try!(emit_user_action_code(grammar, rust, i, defn, data))
            }
            r::ActionFnDefnKind::Lookaround(ref variant) => {
                try!(emit_lookaround_action_code(grammar, rust, i, defn, variant))
            }
            r::ActionFnDefnKind::Inline(ref data) => {
                try!(emit_inline_action_code(grammar, rust, i, defn, data))
            }
        }
    }

    Ok(())
}

fn ret_type_string(grammar: &r::Grammar, defn: &r::ActionFnDefn) -> String {
    if defn.fallible {
        format!(
            "Result<{},{}lalrpop_util::ParseError<{},{},{}>>",
            defn.ret_type,
            grammar.prefix,
            grammar.types.terminal_loc_type(),
            grammar.types.terminal_token_type(),
            grammar.types.error_type()
        )
    } else {
        format!("{}", defn.ret_type)
    }
}

fn emit_user_action_code<W: Write>(
    grammar: &r::Grammar,
    rust: &mut RustWrite<W>,
    index: usize,
    defn: &r::ActionFnDefn,
    data: &r::UserActionFnDefn,
) -> io::Result<()> {
    let ret_type = ret_type_string(grammar, defn);

    // For each symbol to be reduced, we will receive
    // a (L, T, L) triple where the Ls are locations and
    // the T is the data. Ignore the locations and bind
    // the data to the name the user gave.
    let mut arguments: Vec<String> = data
        .arg_patterns
        .iter()
        .zip(
            data.arg_types
                .iter()
                .cloned()
                .map(|t| grammar.types.spanned_type(t)),
        )
        .map(|(p, t)| format!("(_, {}, _): {}", p, t))
        .collect();

    // If this is a reduce of an empty production, we will
    // automatically add position information in the form of
    // lookbehind/lookahead values. Otherwise, those values would be
    // determined from the arguments themselves.
    if data.arg_patterns.is_empty() {
        arguments.extend(vec![
            format!(
                "{}lookbehind: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
            format!(
                "{}lookahead: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
        ]);
    }

    try!(rust.write_fn_header(
        grammar,
        &r::Visibility::Priv,
        format!("{}action{}", grammar.prefix, index),
        vec![],
        None,
        arguments,
        ret_type,
        vec![]
    ));
    rust!(rust, "{{");
    rust!(rust, "{}", data.code);
    rust!(rust, "}}");
    Ok(())
}

fn emit_lookaround_action_code<W: Write>(
    grammar: &r::Grammar,
    rust: &mut RustWrite<W>,
    index: usize,
    _defn: &r::ActionFnDefn,
    data: &r::LookaroundActionFnDefn,
) -> io::Result<()> {
    try!(rust.write_fn_header(
        grammar,
        &r::Visibility::Priv,
        format!("{}action{}", grammar.prefix, index),
        vec![],
        None,
        vec![
            format!(
                "{}lookbehind: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
            format!(
                "{}lookahead: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
        ],
        format!("{}", grammar.types.terminal_loc_type()),
        vec![]
    ));

    rust!(rust, "{{");
    match *data {
        r::LookaroundActionFnDefn::Lookahead => {
            // take the lookahead, if any; otherwise, we are
            // at EOF, so taker the lookbehind (end of last
            // pushed token); if that is missing too, then
            // supply default.
            rust!(rust, "{}lookahead.clone()", grammar.prefix);
        }
        r::LookaroundActionFnDefn::Lookbehind => {
            // take lookbehind or supply default
            rust!(rust, "{}lookbehind.clone()", grammar.prefix);
        }
    }
    rust!(rust, "}}");
    Ok(())
}

fn emit_inline_action_code<W: Write>(
    grammar: &r::Grammar,
    rust: &mut RustWrite<W>,
    index: usize,
    defn: &r::ActionFnDefn,
    data: &r::InlineActionFnDefn,
) -> io::Result<()> {
    let ret_type = ret_type_string(grammar, defn);

    let arg_types: Vec<_> = data
        .symbols
        .iter()
        .flat_map(|sym| match *sym {
            r::InlinedSymbol::Original(ref s) => vec![s.clone()],
            r::InlinedSymbol::Inlined(_, ref syms) => syms.clone(),
        })
        .map(|s| s.ty(&grammar.types))
        .collect();

    // this is the number of symbols we expect to be passed in; it is
    // distinct from data.symbols.len(), because sometimes we have
    // inlined actions with no input symbols
    let num_flat_args = arg_types.len();

    let mut arguments: Vec<_> = arg_types
        .iter()
        .map(|&t| grammar.types.spanned_type(t.clone()))
        .enumerate()
        .map(|(i, t)| format!("{}{}: {}", grammar.prefix, i, t))
        .collect();

    // If no symbols are being reduced, add in the
    // lookbehind/lookahead.
    if arguments.len() == 0 {
        arguments.extend(vec![
            format!(
                "{}lookbehind: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
            format!(
                "{}lookahead: &{}",
                grammar.prefix,
                grammar.types.terminal_loc_type()
            ),
        ]);
    }

    try!(rust.write_fn_header(
        grammar,
        &r::Visibility::Priv,
        format!("{}action{}", grammar.prefix, index),
        vec![],
        None,
        arguments,
        ret_type,
        vec![]
    ));
    rust!(rust, "{{");

    // For each inlined thing, compute the start/end locations.
    // Do this first so that none of the arguments have been moved
    // yet and we can easily access their locations.
    let mut arg_counter = 0;
    let mut temp_counter = 0;
    for symbol in &data.symbols {
        match *symbol {
            r::InlinedSymbol::Original(_) => {
                arg_counter += 1;
            }
            r::InlinedSymbol::Inlined(_, ref syms) => {
                if syms.len() > 0 {
                    // If we are reducing symbols, then start and end
                    // can be the start/end location of the first/last
                    // symbol respectively. Easy peezy.

                    rust!(
                        rust,
                        "let {}start{} = {}{}.0.clone();",
                        grammar.prefix,
                        temp_counter,
                        grammar.prefix,
                        arg_counter
                    );

                    let last_arg_index = arg_counter + syms.len() - 1;
                    rust!(
                        rust,
                        "let {}end{} = {}{}.2.clone();",
                        grammar.prefix,
                        temp_counter,
                        grammar.prefix,
                        last_arg_index
                    );
                } else {
                    // If we have no symbols, then `arg_counter`
                    // represents index of the first symbol after this
                    // inlined item (if any), and `arg_counter-1`
                    // represents index of the symbol before this
                    // item.

                    if arg_counter > 0 {
                        rust!(
                            rust,
                            "let {}start{} = {}{}.2.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix,
                            arg_counter - 1
                        );
                    } else if num_flat_args > 0 {
                        rust!(
                            rust,
                            "let {}start{} = {}{}.0.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix,
                            arg_counter
                        );
                    } else {
                        rust!(
                            rust,
                            "let {}start{} = {}lookbehind.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix
                        );
                    }

                    if arg_counter < num_flat_args {
                        rust!(
                            rust,
                            "let {}end{} = {}{}.0.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix,
                            arg_counter
                        );
                    } else if num_flat_args > 0 {
                        rust!(
                            rust,
                            "let {}end{} = {}{}.2.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix,
                            num_flat_args - 1
                        );
                    } else {
                        rust!(
                            rust,
                            "let {}end{} = {}lookahead.clone();",
                            grammar.prefix,
                            temp_counter,
                            grammar.prefix
                        );
                    }
                }

                temp_counter += 1;
                arg_counter += syms.len();
            }
        }
    }

    // Now create temporaries for the inlined things
    let mut arg_counter = 0;
    let mut temp_counter = 0;

    // if there are type parameters then type annotation is required
    let annotate = !grammar.non_lifetime_type_parameters().is_empty();
    let lparen = if annotate {"::<"} else {"("};

    for symbol in &data.symbols {
        match *symbol {
            r::InlinedSymbol::Original(_) => {
                arg_counter += 1;
            }
            r::InlinedSymbol::Inlined(inlined_action, ref syms) => {
                // execute the inlined reduce action
                rust!(
                    rust,
                    "let {}temp{} = {}action{}{}",
                    grammar.prefix,
                    temp_counter,
                    grammar.prefix,
                    inlined_action.index(),
                    lparen
                );
                for t in grammar.non_lifetime_type_parameters() {
                    rust!(rust, "{},", t);
                }
                if annotate {rust!(rust, ">(")};
                for parameter in &grammar.parameters {
                    rust!(rust, "{},", parameter.name);
                }
                for i in 0..syms.len() {
                    rust!(rust, "{}{},", grammar.prefix, arg_counter + i);
                }
                if syms.len() == 0 {
                    rust!(rust, "&{}start{},", grammar.prefix, temp_counter);
                    rust!(rust, "&{}end{},", grammar.prefix, temp_counter);
                }
                rust!(rust, ");");

                // wrap up the inlined value along with its span
                rust!(
                    rust,
                    "let {}temp{} = ({}start{}, {}temp{}, {}end{});",
                    grammar.prefix,
                    temp_counter,
                    grammar.prefix,
                    temp_counter,
                    grammar.prefix,
                    temp_counter,
                    grammar.prefix,
                    temp_counter
                );

                temp_counter += 1;
                arg_counter += syms.len();
            }
        }
    }
    rust!(rust, "{}action{}{}", grammar.prefix, data.action.index(), lparen);
    for t in grammar.non_lifetime_type_parameters() {
        rust!(rust, "{},", t);
    }
    if annotate {rust!(rust, ">(")};
    for parameter in &grammar.parameters {
        rust!(rust, "{},", parameter.name);
    }
    let mut arg_counter = 0;
    let mut temp_counter = 0;
    for symbol in &data.symbols {
        match *symbol {
            r::InlinedSymbol::Original(_) => {
                rust!(rust, "{}{},", grammar.prefix, arg_counter);
                arg_counter += 1;
            }
            r::InlinedSymbol::Inlined(_, ref syms) => {
                rust!(rust, "{}temp{},", grammar.prefix, temp_counter);
                temp_counter += 1;
                arg_counter += syms.len();
            }
        }
    }
    assert!(data.symbols.len() > 0);
    rust!(rust, ")");

    rust!(rust, "}}");
    Ok(())
}
<|endoftext|>


<commit_before>use command::Command;
use vm::VM;

pub struct Program {
    instructions : Vec<Command>,
    instruction_pointer: Option<usize>,
    is_seeking: bool,
    current_depth: u64,
    goal_depth: Option<u64>,
}

impl Program {
    pub fn new () -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            is_seeking: false,
            current_depth: 0,
            goal_depth: None,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() { self.instruction_pointer = Some(0); }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match self.instruction_pointer {
            None => {},
            Some(mut index) => {
                while index < self.instructions.len() {
                    let command = self.instructions[index];
                    if command == Command::JumpForward {
                        index = self.handle_jump_forward(vm, index);
                    } else if command == Command::JumpBackward {
                        self.current_depth = self.current_depth - 1
                    } else {
                        vm.apply(command);
                        index = index + 1;
                    }
                }
                self.instruction_pointer = Some(index);
            }
        }
    }

    fn seek_forward(&mut self, mut index: usize) -> usize {
        while self.current_depth != self.goal_depth.unwrap() && index < self.instructions.len() {
            match self.instructions[index] {
                Command::JumpForward => self.current_depth = self.current_depth + 1,
                Command::JumpBackward => self.current_depth = self.current_depth - 1,
                _ => {},
            }
            index = index + 1;
        }
        return index;
    }

    fn handle_jump_forward(&mut self, vm: &VM, index: usize) -> usize {
        if vm.cells[vm.data_pointer] == 0 {
            self.goal_depth = Some(self.current_depth);
            return self.seek_forward(index)
        } else {
            self.current_depth = self.current_depth + 1;
            return index;
        }
    }
}
<commit_msg>Avoid repeated unwraps<commit_after>use command::Command;
use vm::VM;

pub struct Program {
    instructions : Vec<Command>,
    instruction_pointer: Option<usize>,
    is_seeking: bool,
    current_depth: u64,
    goal_depth: Option<u64>,
}

impl Program {
    pub fn new () -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            is_seeking: false,
            current_depth: 0,
            goal_depth: None,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() { self.instruction_pointer = Some(0); }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match self.instruction_pointer {
            None => {},
            Some(mut index) => {
                while index < self.instructions.len() {
                    let command = self.instructions[index];
                    if command == Command::JumpForward {
                        index = self.handle_jump_forward(vm, index);
                    } else if command == Command::JumpBackward {
                        self.current_depth = self.current_depth - 1
                    } else {
                        vm.apply(command);
                        index = index + 1;
                    }
                }
                self.instruction_pointer = Some(index);
            }
        }
    }

    fn seek_forward(&mut self, mut index: usize) -> usize {
        let goal_depth = self.goal_depth.unwrap();
        while self.current_depth != goal_depth && index < self.instructions.len() {
            match self.instructions[index] {
                Command::JumpForward => self.current_depth = self.current_depth + 1,
                Command::JumpBackward => self.current_depth = self.current_depth - 1,
                _ => {},
            }
            index = index + 1;
        }
        return index;
    }

    fn handle_jump_forward(&mut self, vm: &VM, index: usize) -> usize {
        if vm.cells[vm.data_pointer] == 0 {
            self.goal_depth = Some(self.current_depth);
            return self.seek_forward(index)
        } else {
            self.current_depth = self.current_depth + 1;
            return index;
        }
    }
}
<|endoftext|>


<commit_before>//! This is an internal module used by the ifmt! runtime. These structures are
//! emitted to static arrays to precompile format strings ahead of time.
//!
//! These definitions are similar to their `ct` equivalents, but differ in that
//! these can be statically allocated and are slightly optimized for the runtime
#![allow(missing_debug_implementations)]

#[derive(Copy, Clone)]
pub struct Argument {
    pub position: usize,
    pub format: FormatSpec,
}

#[derive(Copy, Clone)]
pub struct FormatSpec {
    pub fill: char,
    pub align: Alignment,
    pub flags: u32,
    pub precision: Count,
    pub width: Count,
}

/// Possible alignments that can be requested as part of a formatting directive.
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Alignment {
    /// Indication that contents should be left-aligned.
    Left,
    /// Indication that contents should be right-aligned.
    Right,
    /// Indication that contents should be center-aligned.
    Center,
    /// No alignment was requested.
    Unknown,
}

#[derive(Copy, Clone)]
pub enum Count {
    Is(usize),
    Param(usize),
    Implied,
}
<commit_msg>Document `core::fmt::rt::v1::Count`<commit_after>//! This is an internal module used by the ifmt! runtime. These structures are
//! emitted to static arrays to precompile format strings ahead of time.
//!
//! These definitions are similar to their `ct` equivalents, but differ in that
//! these can be statically allocated and are slightly optimized for the runtime
#![allow(missing_debug_implementations)]

#[derive(Copy, Clone)]
pub struct Argument {
    pub position: usize,
    pub format: FormatSpec,
}

#[derive(Copy, Clone)]
pub struct FormatSpec {
    pub fill: char,
    pub align: Alignment,
    pub flags: u32,
    pub precision: Count,
    pub width: Count,
}

/// Possible alignments that can be requested as part of a formatting directive.
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Alignment {
    /// Indication that contents should be left-aligned.
    Left,
    /// Indication that contents should be right-aligned.
    Right,
    /// Indication that contents should be center-aligned.
    Center,
    /// No alignment was requested.
    Unknown,
}

/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers.
#[derive(Copy, Clone)]
pub enum Count {
    /// Specified with a literal number, stores the value
    Is(usize),
    /// Specified using `$` and `*` syntaxes, stores the index into `args`
    Param(usize),
    /// Not specified
    Implied,
}
<|endoftext|>


<commit_before>use rustc_data_structures::sync::{RwLock, ReadGuard, MappedReadGuard};

/// The `Steal` struct is intended to used as the value for a query.
/// Specifically, we sometimes have queries (*cough* MIR *cough*)
/// where we create a large, complex value that we want to iteratively
/// update (e.g., optimize). We could clone the value for each
/// optimization, but that'd be expensive. And yet we don't just want
/// to mutate it in place, because that would spoil the idea that
/// queries are these pure functions that produce an immutable value
/// (since if you did the query twice, you could observe the
/// mutations). So instead we have the query produce a `&'tcx
/// Steal<Mir<'tcx>>` (to be very specific). Now we can read from this
/// as much as we want (using `borrow()`), but you can also
/// `steal()`. Once you steal, any further attempt to read will panic.
/// Therefore, we know that -- assuming no ICE -- nobody is observing
/// the fact that the MIR was updated.
///
/// Obviously, whenever you have a query that yields a `Steal` value,
/// you must treat it with caution, and make sure that you know that
/// -- once the value is stolen -- it will never be read from again.
//
// FIXME(#41710): what is the best way to model linear queries?
pub struct Steal<T> {
    value: RwLock<Option<T>>
}

impl<T> Steal<T> {
    pub fn new(value: T) -> Self {
        Steal {
            value: RwLock::new(Some(value))
        }
    }

    pub fn borrow(&self) -> MappedReadGuard<'_, T> {
        ReadGuard::map(self.value.borrow(), |opt| match *opt {
            None => bug!("attempted to read from stolen value"),
            Some(ref v) => v
        })
    }

    pub fn steal(&self) -> T {
        let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
        let value = value_ref.take();
        value.expect("attempt to read from stolen value")
    }

    pub fn stolen(&self) -> bool {
        self.value.borrow().is_none()
    }
}
<commit_msg>Remove `stolen`<commit_after>use rustc_data_structures::sync::{RwLock, ReadGuard, MappedReadGuard};

/// The `Steal` struct is intended to used as the value for a query.
/// Specifically, we sometimes have queries (*cough* MIR *cough*)
/// where we create a large, complex value that we want to iteratively
/// update (e.g., optimize). We could clone the value for each
/// optimization, but that'd be expensive. And yet we don't just want
/// to mutate it in place, because that would spoil the idea that
/// queries are these pure functions that produce an immutable value
/// (since if you did the query twice, you could observe the
/// mutations). So instead we have the query produce a `&'tcx
/// Steal<Mir<'tcx>>` (to be very specific). Now we can read from this
/// as much as we want (using `borrow()`), but you can also
/// `steal()`. Once you steal, any further attempt to read will panic.
/// Therefore, we know that -- assuming no ICE -- nobody is observing
/// the fact that the MIR was updated.
///
/// Obviously, whenever you have a query that yields a `Steal` value,
/// you must treat it with caution, and make sure that you know that
/// -- once the value is stolen -- it will never be read from again.
//
// FIXME(#41710): what is the best way to model linear queries?
pub struct Steal<T> {
    value: RwLock<Option<T>>
}

impl<T> Steal<T> {
    pub fn new(value: T) -> Self {
        Steal {
            value: RwLock::new(Some(value))
        }
    }

    pub fn borrow(&self) -> MappedReadGuard<'_, T> {
        ReadGuard::map(self.value.borrow(), |opt| match *opt {
            None => bug!("attempted to read from stolen value"),
            Some(ref v) => v
        })
    }

    pub fn steal(&self) -> T {
        let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
        let value = value_ref.take();
        value.expect("attempt to read from stolen value")
    }
}
<|endoftext|>