<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 byteorder::{LittleEndian, WriteBytesExt};
use euclid::{Point2D, Size2D};
use ipc_channel::ipc::{self, IpcBytesSender, IpcSender};
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::cell::Cell;
use {ApiMsg, AuxiliaryLists, BuiltDisplayList, ColorF, DisplayListId, Epoch};
use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState};
use {StackingContext, StackingContextId, WebGLContextId, WebGLCommand};

impl RenderApiSender {
    pub fn new(api_sender: IpcSender<ApiMsg>,
               payload_sender: IpcBytesSender)
               -> RenderApiSender {
        RenderApiSender {
            api_sender: api_sender,
            payload_sender: payload_sender,
        }
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender {
            ref api_sender,
            ref payload_sender
        } = *self;
        let (sync_tx, sync_rx) = ipc::channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        api_sender.send(msg).unwrap();
        RenderApi {
            api_sender: api_sender.clone(),
            payload_sender: payload_sender.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub api_sender: IpcSender<ApiMsg>,
    pub payload_sender: IpcBytesSender,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     format: ImageFormat,
                     bytes: Vec<u8>) -> ImageKey {
        let new_id = self.next_unique_id();
        let key = ImageKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
    }

    pub fn delete_image(&self, key: ImageKey) {
        let msg = ApiMsg::DeleteImage(key);
        self.api_sender.send(msg).unwrap();
    }

    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.api_sender.send(msg).unwrap();
    }

    /// Supplies a new frame to WebRender.
    ///
    /// Arguments:
    ///
    /// * `stacking_context_id`: The ID of the root stacking context.
    /// * `background_color`: The background color of this pipeline.
    /// * `epoch`: A monotonically increasing timestamp.
    /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
    /// * `viewport_size`: The size of the viewport for this frame.
    /// * `stacking_contexts`: Stacking contexts used in this frame.
    /// * `display_lists`: Display lists used in this frame.
    /// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
    pub fn set_root_stacking_context(&self,
                                     stacking_context_id: StackingContextId,
                                     background_color: ColorF,
                                     epoch: Epoch,
                                     pipeline_id: PipelineId,
                                     viewport_size: Size2D<f32>,
                                     stacking_contexts: Vec<(StackingContextId, StackingContext)>,
                                     display_lists: Vec<(DisplayListId, BuiltDisplayList)>,
                                     auxiliary_lists: AuxiliaryLists) {
        let display_list_descriptors = display_lists.iter().map(|&(display_list_id,
                                                                   ref built_display_list)| {
            (display_list_id, (*built_display_list.descriptor()).clone())
        }).collect();
        let msg = ApiMsg::SetRootStackingContext(stacking_context_id,
                                                 background_color,
                                                 epoch,
                                                 pipeline_id,
                                                 viewport_size,
                                                 stacking_contexts,
                                                 display_list_descriptors,
                                                 *auxiliary_lists.descriptor());
        self.api_sender.send(msg).unwrap();

        let mut payload = vec![];
        payload.write_u32::<LittleEndian>(stacking_context_id.0).unwrap();
        payload.write_u32::<LittleEndian>(epoch.0).unwrap();

        for &(_, ref built_display_list) in &display_lists {
            payload.extend_from_slice(built_display_list.data());
        }
        payload.extend_from_slice(auxiliary_lists.data());

        self.payload_sender.send(&payload[..]).unwrap();
    }

    pub fn scroll(&self, delta: Point2D<f32>, cursor: Point2D<f32>, phase: ScrollEventPhase) {
        let msg = ApiMsg::Scroll(delta, cursor, phase);
        self.api_sender.send(msg).unwrap();
    }

    pub fn tick_scrolling_bounce_animations(&self) {
        let msg = ApiMsg::TickScrollingBounce;
        self.api_sender.send(msg).unwrap();
    }

    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>)
                                          -> (Point2D<f32>, PipelineId) {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::GetScrollLayerState(tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn request_webgl_context(&self, size: &Size2D<i32>, attributes: GLContextAttributes)
                                 -> Result<(WebGLContextId, GLLimits), String> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::RequestWebGLContext(*size, attributes, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn send_webgl_command(&self, context_id: WebGLContextId, command: WebGLCommand) {
        let msg = ApiMsg::WebGLCommand(context_id, command);
        self.api_sender.send(msg).unwrap();
    }

    #[inline]
    pub fn next_stacking_context_id(&self) -> StackingContextId {
        let new_id = self.next_unique_id();
        StackingContextId(new_id.0, new_id.1)
    }

    #[inline]
    pub fn next_display_list_id(&self) -> DisplayListId {
        let new_id = self.next_unique_id();
        DisplayListId(new_id.0, new_id.1)
    }

    #[inline]
    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}
<commit_msg>Improve set_root_stacking_context Documentation<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 byteorder::{LittleEndian, WriteBytesExt};
use euclid::{Point2D, Size2D};
use ipc_channel::ipc::{self, IpcBytesSender, IpcSender};
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::cell::Cell;
use {ApiMsg, AuxiliaryLists, BuiltDisplayList, ColorF, DisplayListId, Epoch};
use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState};
use {StackingContext, StackingContextId, WebGLContextId, WebGLCommand};

impl RenderApiSender {
    pub fn new(api_sender: IpcSender<ApiMsg>,
               payload_sender: IpcBytesSender)
               -> RenderApiSender {
        RenderApiSender {
            api_sender: api_sender,
            payload_sender: payload_sender,
        }
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender {
            ref api_sender,
            ref payload_sender
        } = *self;
        let (sync_tx, sync_rx) = ipc::channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        api_sender.send(msg).unwrap();
        RenderApi {
            api_sender: api_sender.clone(),
            payload_sender: payload_sender.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub api_sender: IpcSender<ApiMsg>,
    pub payload_sender: IpcBytesSender,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     format: ImageFormat,
                     bytes: Vec<u8>) -> ImageKey {
        let new_id = self.next_unique_id();
        let key = ImageKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
    }

    pub fn delete_image(&self, key: ImageKey) {
        let msg = ApiMsg::DeleteImage(key);
        self.api_sender.send(msg).unwrap();
    }

    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.api_sender.send(msg).unwrap();
    }

    /// Supplies a new frame to WebRender.
    ///
    /// Non-blocking, it notifies a worker process which processes the stacking context.
    /// When it's done and a RenderNotifier has been set in `webrender::renderer::Renderer`,
    /// [RenderNotifier][notifier] gets called.
    ///
    /// Note: Scrolling doesn't require an own Frame.
    ///
    /// Arguments:
    ///
    /// * `stacking_context_id`: The ID of the root stacking context.
    /// * `background_color`: The background color of this pipeline.
    /// * `epoch`: The unique Frame ID, monotonically increasing.
    /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
    /// * `viewport_size`: The size of the viewport for this frame.
    /// * `stacking_contexts`: Stacking contexts used in this frame.
    /// * `display_lists`: Display lists used in this frame.
    /// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
    ///
    /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
    pub fn set_root_stacking_context(&self,
                                     stacking_context_id: StackingContextId,
                                     background_color: ColorF,
                                     epoch: Epoch,
                                     pipeline_id: PipelineId,
                                     viewport_size: Size2D<f32>,
                                     stacking_contexts: Vec<(StackingContextId, StackingContext)>,
                                     display_lists: Vec<(DisplayListId, BuiltDisplayList)>,
                                     auxiliary_lists: AuxiliaryLists) {
        let display_list_descriptors = display_lists.iter().map(|&(display_list_id,
                                                                   ref built_display_list)| {
            (display_list_id, (*built_display_list.descriptor()).clone())
        }).collect();
        let msg = ApiMsg::SetRootStackingContext(stacking_context_id,
                                                 background_color,
                                                 epoch,
                                                 pipeline_id,
                                                 viewport_size,
                                                 stacking_contexts,
                                                 display_list_descriptors,
                                                 *auxiliary_lists.descriptor());
        self.api_sender.send(msg).unwrap();

        let mut payload = vec![];
        payload.write_u32::<LittleEndian>(stacking_context_id.0).unwrap();
        payload.write_u32::<LittleEndian>(epoch.0).unwrap();

        for &(_, ref built_display_list) in &display_lists {
            payload.extend_from_slice(built_display_list.data());
        }
        payload.extend_from_slice(auxiliary_lists.data());

        self.payload_sender.send(&payload[..]).unwrap();
    }

    pub fn scroll(&self, delta: Point2D<f32>, cursor: Point2D<f32>, phase: ScrollEventPhase) {
        let msg = ApiMsg::Scroll(delta, cursor, phase);
        self.api_sender.send(msg).unwrap();
    }

    pub fn tick_scrolling_bounce_animations(&self) {
        let msg = ApiMsg::TickScrollingBounce;
        self.api_sender.send(msg).unwrap();
    }

    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>)
                                          -> (Point2D<f32>, PipelineId) {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::GetScrollLayerState(tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn request_webgl_context(&self, size: &Size2D<i32>, attributes: GLContextAttributes)
                                 -> Result<(WebGLContextId, GLLimits), String> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::RequestWebGLContext(*size, attributes, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn send_webgl_command(&self, context_id: WebGLContextId, command: WebGLCommand) {
        let msg = ApiMsg::WebGLCommand(context_id, command);
        self.api_sender.send(msg).unwrap();
    }

    #[inline]
    pub fn next_stacking_context_id(&self) -> StackingContextId {
        let new_id = self.next_unique_id();
        StackingContextId(new_id.0, new_id.1)
    }

    #[inline]
    pub fn next_display_list_id(&self) -> DisplayListId {
        let new_id = self.next_unique_id();
        DisplayListId(new_id.0, new_id.1)
    }

    #[inline]
    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::time::Duration;
use time::precise_time_ns;

use bootstrap::{Context, Keyboard, Mouse, MouseMove, Scroll, Window};
pub use bootstrap::{Action, Key, MouseButton};
use camera::{Camera, Freefly};
use transform::Translation;

#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Unhandled;

/// Class of keyboard handlers.
pub trait KeyboardHandler {
  fn on_key(&mut self, key: Key, action: Action) -> bool;
}

impl KeyboardHandler for Unhandled {
  fn on_key(&mut self, _: Key, _: Action) -> bool { true }
}

/// Class of mouse button handlers.
pub trait MouseButtonHandler {
  fn on_mouse_button(&mut self, button: MouseButton, action: Action) -> bool;
}

impl MouseButtonHandler for Unhandled {
  fn on_mouse_button(&mut self, _: MouseButton, _: Action) -> bool { true }
}

/// Class of mouse move handlers.
pub trait CursorHandler {
  fn on_cursor_move(&mut self, cursor_pos: [f64; 2]) -> bool;
}

impl CursorHandler for Unhandled {
  fn on_cursor_move(&mut self, _: [f64; 2]) -> bool { true }
}

/// Class of scroll handlers.
pub trait ScrollHandler {
  fn on_scroll(&mut self, scroll_dir: [f64; 2]) -> bool;
}

impl ScrollHandler for Unhandled {
  fn on_scroll(&mut self, _: [f64; 2]) -> bool { true }
}

/// All common stuff goes here.
pub struct App {
  /// Some kind of epoch start the application started at.
  start_time: u64,
  /// Keyboard receiver.
  kbd: Keyboard,
  /// Mouse receiver.
  mouse: Mouse,
  /// Cursor receiver.
  cursor: MouseMove,
  /// Scroll receiver.
  scroll: Scroll,
  /// Window.
  window: Window,
}

impl App {
  pub fn init(kbd: Keyboard, mouse: Mouse, cursor: MouseMove, scroll: Scroll, window: Window) -> Self {
    App {
      start_time: precise_time_ns(),
      kbd: kbd,
      mouse: mouse,
      cursor: cursor,
      scroll: scroll,
      window: window
    }
  }

  pub fn time(&self) -> f32 {
    (precise_time_ns() - self.start_time) as f32 * 1e-9
  }

  pub fn dispatch_events<K, MB, MM, S>(&self,
                                       keyboard_handler: &mut K,
                                       mouse_button_handler: &mut MB,
                                       cursor_handler: &mut MM,
                                       scroll_handler: &mut S) -> bool
      where K: KeyboardHandler,
            MB: MouseButtonHandler,
            MM: CursorHandler,
            S: ScrollHandler {
    while let Ok((key, action)) = self.kbd.try_recv() {
      if !keyboard_handler.on_key(key, action) {
        return false;
      }
    }

    while let Ok((button, action)) = self.mouse.try_recv() {
      if !mouse_button_handler.on_mouse_button(button, action) {
        return false;
      }
    }

    while let Ok(xy) = self.cursor.try_recv() {
      if !cursor_handler.on_cursor_move(xy) {
        return false;
      }
    }

    while let Ok(xy) = self.scroll.try_recv() {
      if !scroll_handler.on_scroll(xy) {
        return false;
      }
    }

    true
  }

  pub fn step<R>(&mut self, fps: Option<u32>, mut draw_frame: R) -> bool where R: FnMut(f32) {
    let loop_start_time = precise_time_ns();

    if self.window.should_close() {
      return false;
    }

    let t = self.time();

    draw_frame(t);

    self.window.swap_buffers();

    // wait for next frame according to the wished FPS
    if let Some(fps) = fps {
      let fps = fps as f32;
      let elapsed_time_ms = ((precise_time_ns() - loop_start_time) as f64 * 1e-6) as i64;
      let sleep_time_ms = (1. / fps * 1e3) as i64 - elapsed_time_ms;

      if sleep_time_ms > 0 {
        thread::sleep(Duration::from_millis(sleep_time_ms as u64));
      }
    }

    true
  }
}
<commit_msg>Using a single handler.<commit_after>use std::thread;
use std::time::Duration;
use time::precise_time_ns;

use bootstrap::{Context, Keyboard, Mouse, MouseMove, Scroll, Window};
pub use bootstrap::{Action, Key, MouseButton};
use camera::{Camera, Freefly};
use transform::Translation;

#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Unhandled;

/// Class of keyboard handlers.
pub trait KeyboardHandler {
  fn on_key(&mut self, key: Key, action: Action) -> bool;
}

impl KeyboardHandler for Unhandled {
  fn on_key(&mut self, _: Key, _: Action) -> bool { true }
}

/// Class of mouse button handlers.
pub trait MouseButtonHandler {
  fn on_mouse_button(&mut self, button: MouseButton, action: Action) -> bool;
}

impl MouseButtonHandler for Unhandled {
  fn on_mouse_button(&mut self, _: MouseButton, _: Action) -> bool { true }
}

/// Class of mouse move handlers.
pub trait CursorHandler {
  fn on_cursor_move(&mut self, cursor_pos: [f64; 2]) -> bool;
}

impl CursorHandler for Unhandled {
  fn on_cursor_move(&mut self, _: [f64; 2]) -> bool { true }
}

/// Class of scroll handlers.
pub trait ScrollHandler {
  fn on_scroll(&mut self, scroll_dir: [f64; 2]) -> bool;
}

impl ScrollHandler for Unhandled {
  fn on_scroll(&mut self, _: [f64; 2]) -> bool { true }
}

/// All common stuff goes here.
pub struct App {
  /// Some kind of epoch start the application started at.
  start_time: u64,
  /// Keyboard receiver.
  kbd: Keyboard,
  /// Mouse receiver.
  mouse: Mouse,
  /// Cursor receiver.
  cursor: MouseMove,
  /// Scroll receiver.
  scroll: Scroll,
  /// Window.
  window: Window,
}

impl App {
  pub fn init(kbd: Keyboard, mouse: Mouse, cursor: MouseMove, scroll: Scroll, window: Window) -> Self {
    App {
      start_time: precise_time_ns(),
      kbd: kbd,
      mouse: mouse,
      cursor: cursor,
      scroll: scroll,
      window: window
    }
  }

  pub fn time(&self) -> f32 {
    (precise_time_ns() - self.start_time) as f32 * 1e-9
  }

  pub fn dispatch_events<H>(&self, handler: &mut H) -> bool
      where H: KeyboardHandler + MouseButtonHandler + CursorHandler + ScrollHandler {
    while let Ok((key, action)) = self.kbd.try_recv() {
      if !handler.on_key(key, action) {
        return false;
      }
    }

    while let Ok((button, action)) = self.mouse.try_recv() {
      if !handler.on_mouse_button(button, action) {
        return false;
      }
    }

    while let Ok(xy) = self.cursor.try_recv() {
      if !handler.on_cursor_move(xy) {
        return false;
      }
    }

    while let Ok(xy) = self.scroll.try_recv() {
      if !handler.on_scroll(xy) {
        return false;
      }
    }

    true
  }

  pub fn step<R>(&mut self, fps: Option<u32>, mut draw_frame: R) -> bool where R: FnMut(f32) {
    let loop_start_time = precise_time_ns();

    if self.window.should_close() {
      return false;
    }

    let t = self.time();

    draw_frame(t);

    self.window.swap_buffers();

    // wait for next frame according to the wished FPS
    if let Some(fps) = fps {
      let fps = fps as f32;
      let elapsed_time_ms = ((precise_time_ns() - loop_start_time) as f64 * 1e-6) as i64;
      let sleep_time_ms = (1. / fps * 1e3) as i64 - elapsed_time_ms;

      if sleep_time_ms > 0 {
        thread::sleep(Duration::from_millis(sleep_time_ms as u64));
      }
    }

    true
  }
}
<|endoftext|>


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

#[derive(Debug, PartialEq, Eq)]
pub enum BinOp {
    And,
    Minus,
    Or,
    Plus,
    Slash,
    Star,
}

#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub enum Precedence {
    Const = 110,
    Sign = 100,
    Inc = 90,
    Mult = 60,
    Add = 50,
    And = 40,
    Or = 30,
}

impl BinOp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            BinOp::And => Precedence::And,
            BinOp::Or => Precedence::Or,
            BinOp::Minus | BinOp::Plus => Precedence::Add,
            BinOp::Slash | BinOp::Star => Precedence::Mult,
        }
    }

    pub fn is_commutative(&self) -> bool {
        match *self {
            BinOp::Minus | BinOp::Slash => false,
            _ => true
        }
    }
}

impl Display for BinOp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            BinOp::And => write!(fmt, "&&"),
            BinOp::Minus => write!(fmt, "-"),
            BinOp::Or => write!(fmt, "||"),
            BinOp::Plus => write!(fmt, "+"),
            BinOp::Slash => write!(fmt, "/"),
            BinOp::Star => write!(fmt, "*"),
        }
    }
}

#[derive(Debug)]
pub enum Exp {
    BinExp(Box<Exp>, BinOp, Box<Exp>),
    Bool(bool),
    Float(f64),
    Neg(Box<Exp>),
    Pos(Box<Exp>),
    PostDec(Box<Exp>),
    PostInc(Box<Exp>),
    PreDec(Box<Exp>),
    PreInc(Box<Exp>),
    Undefined,
    Var(String),
}

impl Exp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            Exp::BinExp(_, ref o, _) => o.precedence(),
            Exp::Bool(_) | Exp::Float(_) | Exp::Undefined | Exp::Var(_) => Precedence::Const,
            Exp::Neg(_) | Exp::Pos(_) => Precedence::Sign,
            Exp::PostDec(_) | Exp::PostInc(_) | Exp::PreDec(_) | Exp::PreInc(_) => Precedence::Inc,
        }
    }
}

macro_rules! group {
    ($e:expr, $p:expr) => {
        if $e.precedence() < $p {
            format!("({})", $e)
        } else {
            format!("{}", $e)
        }
    }
}

impl Display for Exp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            Exp::BinExp(ref e1, ref o, ref e2) => {
                let prec = self.precedence();

                // Put grouping parentheses if the left subexpression has a lower-precedence
                // operator, e.g. (1 + 2) * 3
                let left = if prec > e1.precedence() {
                    format!("({})", e1)
                } else {
                    format!("{}", e1)
                };

                let right_prec = e2.precedence();

                // Put grouping parentheses around the right subexpression if it has a
                // lower-precedence operator,  __OR__ if `o` is not commutative and the precedence
                // is the same, e.g. (1 + 2) * 3 __OR__ 1 - (2 + 3)
                let right = if prec > right_prec || (!o.is_commutative() && prec == right_prec) {
                    format!("({})", e2)
                } else {
                    format!("{}", e2)
                };

                write!(fmt, "{} {} {}", left, o, right)
            }
            Exp::Bool(b) => write!(fmt, "{}", b),
            Exp::Float(f) => write!(fmt, "{}", f),
            Exp::Neg(ref e) => write!(fmt, "-{}", group!(e, Precedence::Sign)),
            Exp::Pos(ref e) => write!(fmt, "+{}", group!(e, Precedence::Sign)),
            Exp::PostDec(ref e) => write!(fmt, "{}--", group!(e, Precedence::Inc)),
            Exp::PostInc(ref e) => write!(fmt, "{}++", group!(e, Precedence::Inc)),
            Exp::PreDec(ref e) => write!(fmt, "--{}", group!(e, Precedence::Inc)),
            Exp::PreInc(ref e) => write!(fmt, "++{}", group!(e, Precedence::Inc)),
            Exp::Undefined => write!(fmt, "undefined"),
            Exp::Var(ref v) => write!(fmt, "{}", v),
        }
    }
}

#[derive(Debug)]
pub enum Stmt {
    Assign(String, Exp),
    BareExp(Exp),
    Decl(String, Exp),
    If(Exp, Box<Stmt>, Vec<(Exp, Box<Stmt>)>, Option<Box<Stmt>>),
    Seq(Box<Stmt>, Box<Stmt>),
    While(Exp, Box<Stmt>),
}

impl Stmt {
    fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! indented_stmt {
            ($stmt:expr) => {
                try!($stmt.fmt_helper(&mut fmt, indent_level + 2))
            }
        }

        let indent : String = (0..indent_level).map(|_| " ").collect();

        match *self {
            Stmt::Assign(ref v, ref exp) => write!(fmt, "{}{} = {};\n", indent, v, exp),
            Stmt::BareExp(ref exp) => write!(fmt, "{}{};\n", indent, exp),
            Stmt::Decl(ref v, ref exp) => write!(fmt, "{}var {} = {};\n", indent, v, exp),
            Stmt::If(ref e, ref s, ref vec, ref els) => {
                try!(write!(fmt, "{}if ({}) {{\n", indent, e));
                indented_stmt!(s);

                for &(ref exp, ref stmt) in vec {
                    try!(write!(fmt, "{}else if ({}) {{\n", indent, exp));
                    indented_stmt!(stmt);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                if let &Some(ref stmt) = els {
                    try!(write!(fmt, "{} else {{\n", indent));
                    indented_stmt!(stmt);
                }

                Ok(())
            }
            Stmt::Seq(ref s1, ref s2) => write!(fmt, "{}{}{}{}", indent, s1, indent, s2),
            Stmt::While(ref exp, ref stmt) => {
                try!(write!(fmt, "{}while ({}) {{\n", indent, exp));
                try!(stmt.fmt_helper(&mut fmt, indent_level + 2));
                write!(fmt, "{}}}\n", indent)
            }
        }
    }
}

impl Display for Stmt {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}
<commit_msg>get rid of `else if` clauses in favor of nesting<commit_after>use std::fmt::{Display, Error, Formatter};

#[derive(Debug, PartialEq, Eq)]
pub enum BinOp {
    And,
    Minus,
    Or,
    Plus,
    Slash,
    Star,
}

#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub enum Precedence {
    Const = 110,
    Sign = 100,
    Inc = 90,
    Mult = 60,
    Add = 50,
    And = 40,
    Or = 30,
}

impl BinOp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            BinOp::And => Precedence::And,
            BinOp::Or => Precedence::Or,
            BinOp::Minus | BinOp::Plus => Precedence::Add,
            BinOp::Slash | BinOp::Star => Precedence::Mult,
        }
    }

    pub fn is_commutative(&self) -> bool {
        match *self {
            BinOp::Minus | BinOp::Slash => false,
            _ => true
        }
    }
}

impl Display for BinOp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            BinOp::And => write!(fmt, "&&"),
            BinOp::Minus => write!(fmt, "-"),
            BinOp::Or => write!(fmt, "||"),
            BinOp::Plus => write!(fmt, "+"),
            BinOp::Slash => write!(fmt, "/"),
            BinOp::Star => write!(fmt, "*"),
        }
    }
}

#[derive(Debug)]
pub enum Exp {
    BinExp(Box<Exp>, BinOp, Box<Exp>),
    Bool(bool),
    Float(f64),
    Neg(Box<Exp>),
    Pos(Box<Exp>),
    PostDec(Box<Exp>),
    PostInc(Box<Exp>),
    PreDec(Box<Exp>),
    PreInc(Box<Exp>),
    Undefined,
    Var(String),
}

impl Exp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            Exp::BinExp(_, ref o, _) => o.precedence(),
            Exp::Bool(_) | Exp::Float(_) | Exp::Undefined | Exp::Var(_) => Precedence::Const,
            Exp::Neg(_) | Exp::Pos(_) => Precedence::Sign,
            Exp::PostDec(_) | Exp::PostInc(_) | Exp::PreDec(_) | Exp::PreInc(_) => Precedence::Inc,
        }
    }
}

macro_rules! group {
    ($e:expr, $p:expr) => {
        if $e.precedence() < $p {
            format!("({})", $e)
        } else {
            format!("{}", $e)
        }
    }
}

impl Display for Exp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            Exp::BinExp(ref e1, ref o, ref e2) => {
                let prec = self.precedence();

                // Put grouping parentheses if the left subexpression has a lower-precedence
                // operator, e.g. (1 + 2) * 3
                let left = if prec > e1.precedence() {
                    format!("({})", e1)
                } else {
                    format!("{}", e1)
                };

                let right_prec = e2.precedence();

                // Put grouping parentheses around the right subexpression if it has a
                // lower-precedence operator,  __OR__ if `o` is not commutative and the precedence
                // is the same, e.g. (1 + 2) * 3 __OR__ 1 - (2 + 3)
                let right = if prec > right_prec || (!o.is_commutative() && prec == right_prec) {
                    format!("({})", e2)
                } else {
                    format!("{}", e2)
                };

                write!(fmt, "{} {} {}", left, o, right)
            }
            Exp::Bool(b) => write!(fmt, "{}", b),
            Exp::Float(f) => write!(fmt, "{}", f),
            Exp::Neg(ref e) => write!(fmt, "-{}", group!(e, Precedence::Sign)),
            Exp::Pos(ref e) => write!(fmt, "+{}", group!(e, Precedence::Sign)),
            Exp::PostDec(ref e) => write!(fmt, "{}--", group!(e, Precedence::Inc)),
            Exp::PostInc(ref e) => write!(fmt, "{}++", group!(e, Precedence::Inc)),
            Exp::PreDec(ref e) => write!(fmt, "--{}", group!(e, Precedence::Inc)),
            Exp::PreInc(ref e) => write!(fmt, "++{}", group!(e, Precedence::Inc)),
            Exp::Undefined => write!(fmt, "undefined"),
            Exp::Var(ref v) => write!(fmt, "{}", v),
        }
    }
}

#[derive(Debug)]
pub enum Stmt {
    Assign(String, Exp),
    BareExp(Exp),
    Decl(String, Exp),
    If(Exp, Box<Stmt>, Option<Box<Stmt>>),
    Seq(Box<Stmt>, Box<Stmt>),
    While(Exp, Box<Stmt>),
}

impl Stmt {
    fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! indented_stmt {
            ($stmt:expr) => {
                try!($stmt.fmt_helper(&mut fmt, indent_level + 2))
            }
        }

        let indent : String = (0..indent_level).map(|_| " ").collect();

        match *self {
            Stmt::Assign(ref v, ref exp) => write!(fmt, "{}{} = {};\n", indent, v, exp),
            Stmt::BareExp(ref exp) => write!(fmt, "{}{};\n", indent, exp),
            Stmt::Decl(ref v, ref exp) => write!(fmt, "{}var {} = {};\n", indent, v, exp),
            Stmt::If(ref e, ref s, ref els) => {
                try!(write!(fmt, "{}if ({}) {{\n", indent, e));
                indented_stmt!(s);

                if let &Some(ref stmt) = els {
                    try!(write!(fmt, "{}else {{\n", indent));
                    indented_stmt!(stmt);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                Ok(())
            }
            Stmt::Seq(ref s1, ref s2) => write!(fmt, "{}{}{}{}", indent, s1, indent, s2),
            Stmt::While(ref exp, ref stmt) => {
                try!(write!(fmt, "{}while ({}) {{\n", indent, exp));
                try!(stmt.fmt_helper(&mut fmt, indent_level + 2));
                write!(fmt, "{}}}\n", indent)
            }
        }
    }
}

impl Display for Stmt {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}
<|endoftext|>


<commit_before>extern crate mli;
extern crate rand;
use self::rand::Rng;

pub type R = rand::isaac::Isaac64Rng;

pub mod nodebrain {
    //0, 1, 2, -1, rand, node energy, present node energy, bot count, present node bot count, self energy, present node connections, node connections, period, force, and memory are inputs.
    pub const STATIC_INPUTS: usize = 14;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + super::finalbrain::TOTAL_MEMORY;
    pub const TOTAL_OUTPUTS: usize = 5;
    pub const DEFAULT_MUTATE_SIZE: usize = 8;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 32;
}

pub mod botbrain {
    //0, 1, 2, -1, rand, node energy, bot count, self energy, bot energy, bot signal, present node connections, period, force, and memory are inputs.
    pub const STATIC_INPUTS: usize = 13;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + super::finalbrain::TOTAL_MEMORY;
    pub const TOTAL_OUTPUTS: usize = 5;
    pub const DEFAULT_MUTATE_SIZE: usize = 8;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 32;
}

pub mod finalbrain {
    pub const TOTAL_BOT_INPUTS: usize = 4;
    pub const TOTAL_NODE_INPUTS: usize = 4;
    pub const TOTAL_MEMORY: usize = 4;
    //0, 1, 2, -1, rand, present node energy, bot count, self energy, self index, present node connections, period, force, and memory are inputs
    pub const STATIC_INPUTS: usize = 12;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + TOTAL_MEMORY +
        //Add inputs for all the node brains
        TOTAL_NODE_INPUTS * super::nodebrain::TOTAL_OUTPUTS +
        //Add inputs for all the bot brains
        TOTAL_BOT_INPUTS * super::botbrain::TOTAL_OUTPUTS;
    //Mate, Node, Energy Rate (as a sigmoid), Signal, Connect Signal, Pull
    pub const STATIC_OUTPUTS: usize = 7;
    pub const TOTAL_OUTPUTS: usize = STATIC_OUTPUTS + TOTAL_MEMORY;
    pub const DEFAULT_MUTATE_SIZE: usize = 8;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 128;
}

pub const MAX_ENERGY: i64 = 10000000;
pub const MATE_ENERGY: i64 = 100;
pub const ENERGY_EXCHANGE_MAGNITUDE: i64 = MAX_ENERGY;
pub const EXISTENCE_COST: i64 = 1;
const DEFAULT_ENERGY: i64 = 4 * EXISTENCE_COST;
const MUTATE_PROBABILITY: f64 = 1.0;

#[derive(Clone)]
pub enum Ins {
    _NOP,
    _ADD,
    _SUB,
    _MUL,
    _DIV,
    _MOD,
    _GRT,
    _LES,
    _EQL,
    _NEQ,
    _AND,
    _OR,
    _POW,
    _EXP,
    _LN,
    _SIN,
    _SQT,
    MAX,
}

fn processor(ins: &Ins, a: i64, b: i64) -> i64 {
    match *ins {
        Ins::_NOP => a,
        Ins::_ADD => a + b,
        Ins::_SUB => a - b,
        Ins::_MUL => a * b,
        Ins::_DIV => {
            match a.checked_div(b) {
                Some(v) => v,
                None => 0,
            }
        },
        Ins::_MOD => {
            if b == 0 {
                0
            } else {
                a.wrapping_rem(b)
            }
        },
        Ins::_GRT => if a > b {
            1
        } else {
            0
        },
        Ins::_LES => if a < b {
            1
        } else {
            0
        },
        Ins::_EQL => if a == b {
            1
        } else {
            0
        },
        Ins::_NEQ => if a == b {
            1
        } else {
            0
        },
        Ins::_AND => if a != 0 && b != 0 {
            1
        } else {
            0
        },
        Ins::_OR => if a != 0 || b != 0 {
            1
        } else {
            0
        },
        Ins::_POW => (a as f64).powf(b as f64) as i64,
        Ins::_EXP => ((a as f64).exp() * b as f64) as i64,
        Ins::_LN => ((a as f64).ln() * b as f64) as i64,
        Ins::_SIN => ((a as f64 / b as f64).sin() * b as f64) as i64,
        Ins::_SQT => ((a as f64 / b as f64).sqrt() * b as f64) as i64,
        Ins::MAX => unreachable!(),
    }
}

fn mutator(ins: &mut Ins, rng: &mut R) {
    use std::mem;
    *ins = unsafe{mem::transmute(rng.gen_range::<u8>(0, Ins::MAX as u8))};
}

#[derive(Clone)]
pub struct Decision {
    pub mate: i64,
    pub node: i64,
    //This will be ran through a sigmoid
    pub rate: i64,
    pub signal: i64,
    pub connect_signal: i64,
    pub sever_choice: i64,
    pub pull: i64,
}

impl Default for Decision {
    fn default() -> Self {
        Decision{
            mate: -1,
            node: -1,
            rate: 0,
            signal: 0,
            connect_signal: 0,
            sever_choice: 0,
            pull: 0,
        }
    }
}

#[derive(Clone)]
pub struct Bot {
    pub bot_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub node_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub final_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub energy: i64,
    pub signal: i64,
    pub connect_signal: i64,
    pub memory: [i64; finalbrain::TOTAL_MEMORY],
    pub decision: Decision,
}

impl Bot {
    pub fn new(rng: &mut R) -> Self {
        let bvec = (0..botbrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        let nvec = (0..nodebrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        let fvec = (0..finalbrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        Bot {
            bot_brain: mli::Mep::new(botbrain::TOTAL_INPUTS, botbrain::TOTAL_OUTPUTS,
                botbrain::DEFAULT_MUTATE_SIZE, botbrain::DEFAULT_CROSSOVER_POINTS, rng,
                bvec.into_iter(),
                mutator, processor),

            node_brain: mli::Mep::new(nodebrain::TOTAL_INPUTS, nodebrain::TOTAL_OUTPUTS,
                nodebrain::DEFAULT_MUTATE_SIZE, nodebrain::DEFAULT_CROSSOVER_POINTS, rng,
                nvec.into_iter(),
                mutator, processor),

            final_brain: mli::Mep::new(finalbrain::TOTAL_INPUTS, finalbrain::TOTAL_OUTPUTS,
                finalbrain::DEFAULT_MUTATE_SIZE, finalbrain::DEFAULT_CROSSOVER_POINTS, rng,
                fvec.into_iter(),
                mutator, processor),

            energy: DEFAULT_ENERGY,

            signal: 0,
            connect_signal: 0,

            memory: [0; finalbrain::TOTAL_MEMORY],
            decision: Default::default(),
        }
    }

    pub fn mutate(&mut self, rng: &mut R) {
        use mli::Genetic;
        if rng.gen_range(0.0, 1.0) < MUTATE_PROBABILITY {
            self.bot_brain.mutate(rng);
            self.node_brain.mutate(rng);
            self.final_brain.mutate(rng);
        }
    }

    pub fn mate(&mut self, other: &Self, rng: &mut R) -> Self {
        use mli::Genetic;
        //Divide energy in half when mating for the mater
        self.energy /= 2;
        let mut b = Bot{
            bot_brain: mli::Genetic::mate((&self.bot_brain, &other.bot_brain), rng),
            node_brain: mli::Genetic::mate((&self.node_brain, &other.node_brain), rng),
            final_brain: mli::Genetic::mate((&self.final_brain, &other.final_brain), rng),
            energy: self.energy,
            signal: self.signal,
            connect_signal: 0,
            memory: self.memory,
            decision: self.decision.clone(),
        };
        //Perform unit mutations on offspring
        b.mutate(rng);
        b
    }

    pub fn divide(&mut self, rng: &mut R) -> Self {
        use mli::Genetic;
        //Divide energy in half when dividing
        self.energy /= 2;
        let mut b = Bot{
            bot_brain: self.bot_brain.clone(),
            node_brain: self.node_brain.clone(),
            final_brain: self.final_brain.clone(),
            energy: self.energy,
            signal: self.signal,
            connect_signal: 0,
            memory: self.memory,
            //Clone the rate of energy consumption in the decision
            decision: self.decision.clone(),
        };
        //Perform unit mutations on offspring
        b.mutate(rng);
        b
    }

    pub fn cycle(&mut self) {
        self.energy = self.energy.saturating_sub(EXISTENCE_COST);
        self.signal = self.decision.signal;
        self.connect_signal = self.decision.connect_signal;
    }
}
<commit_msg>less agressive is easier to simulate<commit_after>extern crate mli;
extern crate rand;
use self::rand::Rng;

pub type R = rand::isaac::Isaac64Rng;

pub mod nodebrain {
    //0, 1, 2, -1, rand, node energy, present node energy, bot count, present node bot count, self energy, present node connections, node connections, period, force, and memory are inputs.
    pub const STATIC_INPUTS: usize = 14;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + super::finalbrain::TOTAL_MEMORY;
    pub const TOTAL_OUTPUTS: usize = 5;
    pub const DEFAULT_MUTATE_SIZE: usize = 8;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 32;
}

pub mod botbrain {
    //0, 1, 2, -1, rand, node energy, bot count, self energy, bot energy, bot signal, present node connections, period, force, and memory are inputs.
    pub const STATIC_INPUTS: usize = 13;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + super::finalbrain::TOTAL_MEMORY;
    pub const TOTAL_OUTPUTS: usize = 5;
    pub const DEFAULT_MUTATE_SIZE: usize = 8;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 32;
}

pub mod finalbrain {
    pub const TOTAL_BOT_INPUTS: usize = 4;
    pub const TOTAL_NODE_INPUTS: usize = 4;
    pub const TOTAL_MEMORY: usize = 4;
    //0, 1, 2, -1, rand, present node energy, bot count, self energy, self index, present node connections, period, force, and memory are inputs
    pub const STATIC_INPUTS: usize = 12;
    pub const TOTAL_INPUTS: usize = STATIC_INPUTS + TOTAL_MEMORY +
        //Add inputs for all the node brains
        TOTAL_NODE_INPUTS * super::nodebrain::TOTAL_OUTPUTS +
        //Add inputs for all the bot brains
        TOTAL_BOT_INPUTS * super::botbrain::TOTAL_OUTPUTS;
    //Mate, Node, Energy Rate (as a sigmoid), Signal, Connect Signal, Pull
    pub const STATIC_OUTPUTS: usize = 7;
    pub const TOTAL_OUTPUTS: usize = STATIC_OUTPUTS + TOTAL_MEMORY;
    pub const DEFAULT_MUTATE_SIZE: usize = 8;
    pub const DEFAULT_CROSSOVER_POINTS: usize = 1;
    pub const DEFAULT_INSTRUCTIONS: usize = 128;
}

pub const MAX_ENERGY: i64 = 10000000;
pub const MATE_ENERGY: i64 = 10000;
pub const ENERGY_EXCHANGE_MAGNITUDE: i64 = MAX_ENERGY;
pub const EXISTENCE_COST: i64 = 1;
const DEFAULT_ENERGY: i64 = 4 * EXISTENCE_COST;
const MUTATE_PROBABILITY: f64 = 1.0;

#[derive(Clone)]
pub enum Ins {
    _NOP,
    _ADD,
    _SUB,
    _MUL,
    _DIV,
    _MOD,
    _GRT,
    _LES,
    _EQL,
    _NEQ,
    _AND,
    _OR,
    _POW,
    _EXP,
    _LN,
    _SIN,
    _SQT,
    MAX,
}

fn processor(ins: &Ins, a: i64, b: i64) -> i64 {
    match *ins {
        Ins::_NOP => a,
        Ins::_ADD => a + b,
        Ins::_SUB => a - b,
        Ins::_MUL => a * b,
        Ins::_DIV => {
            match a.checked_div(b) {
                Some(v) => v,
                None => 0,
            }
        },
        Ins::_MOD => {
            if b == 0 {
                0
            } else {
                a.wrapping_rem(b)
            }
        },
        Ins::_GRT => if a > b {
            1
        } else {
            0
        },
        Ins::_LES => if a < b {
            1
        } else {
            0
        },
        Ins::_EQL => if a == b {
            1
        } else {
            0
        },
        Ins::_NEQ => if a == b {
            1
        } else {
            0
        },
        Ins::_AND => if a != 0 && b != 0 {
            1
        } else {
            0
        },
        Ins::_OR => if a != 0 || b != 0 {
            1
        } else {
            0
        },
        Ins::_POW => (a as f64).powf(b as f64) as i64,
        Ins::_EXP => ((a as f64).exp() * b as f64) as i64,
        Ins::_LN => ((a as f64).ln() * b as f64) as i64,
        Ins::_SIN => ((a as f64 / b as f64).sin() * b as f64) as i64,
        Ins::_SQT => ((a as f64 / b as f64).sqrt() * b as f64) as i64,
        Ins::MAX => unreachable!(),
    }
}

fn mutator(ins: &mut Ins, rng: &mut R) {
    use std::mem;
    *ins = unsafe{mem::transmute(rng.gen_range::<u8>(0, Ins::MAX as u8))};
}

#[derive(Clone)]
pub struct Decision {
    pub mate: i64,
    pub node: i64,
    //This will be ran through a sigmoid
    pub rate: i64,
    pub signal: i64,
    pub connect_signal: i64,
    pub sever_choice: i64,
    pub pull: i64,
}

impl Default for Decision {
    fn default() -> Self {
        Decision{
            mate: -1,
            node: -1,
            rate: 0,
            signal: 0,
            connect_signal: 0,
            sever_choice: 0,
            pull: 0,
        }
    }
}

#[derive(Clone)]
pub struct Bot {
    pub bot_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub node_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub final_brain: mli::Mep<Ins, R, i64, fn(&mut Ins, &mut R), fn(&Ins, i64, i64) -> i64>,
    pub energy: i64,
    pub signal: i64,
    pub connect_signal: i64,
    pub memory: [i64; finalbrain::TOTAL_MEMORY],
    pub decision: Decision,
}

impl Bot {
    pub fn new(rng: &mut R) -> Self {
        let bvec = (0..botbrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        let nvec = (0..nodebrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        let fvec = (0..finalbrain::DEFAULT_INSTRUCTIONS).map(|_| {
                let mut ins = Ins::_NOP;
                mutator(&mut ins, rng);
                ins
            }).collect::<Vec<_>>();
        Bot {
            bot_brain: mli::Mep::new(botbrain::TOTAL_INPUTS, botbrain::TOTAL_OUTPUTS,
                botbrain::DEFAULT_MUTATE_SIZE, botbrain::DEFAULT_CROSSOVER_POINTS, rng,
                bvec.into_iter(),
                mutator, processor),

            node_brain: mli::Mep::new(nodebrain::TOTAL_INPUTS, nodebrain::TOTAL_OUTPUTS,
                nodebrain::DEFAULT_MUTATE_SIZE, nodebrain::DEFAULT_CROSSOVER_POINTS, rng,
                nvec.into_iter(),
                mutator, processor),

            final_brain: mli::Mep::new(finalbrain::TOTAL_INPUTS, finalbrain::TOTAL_OUTPUTS,
                finalbrain::DEFAULT_MUTATE_SIZE, finalbrain::DEFAULT_CROSSOVER_POINTS, rng,
                fvec.into_iter(),
                mutator, processor),

            energy: DEFAULT_ENERGY,

            signal: 0,
            connect_signal: 0,

            memory: [0; finalbrain::TOTAL_MEMORY],
            decision: Default::default(),
        }
    }

    pub fn mutate(&mut self, rng: &mut R) {
        use mli::Genetic;
        if rng.gen_range(0.0, 1.0) < MUTATE_PROBABILITY {
            self.bot_brain.mutate(rng);
            self.node_brain.mutate(rng);
            self.final_brain.mutate(rng);
        }
    }

    pub fn mate(&mut self, other: &Self, rng: &mut R) -> Self {
        use mli::Genetic;
        //Divide energy in half when mating for the mater
        self.energy /= 2;
        let mut b = Bot{
            bot_brain: mli::Genetic::mate((&self.bot_brain, &other.bot_brain), rng),
            node_brain: mli::Genetic::mate((&self.node_brain, &other.node_brain), rng),
            final_brain: mli::Genetic::mate((&self.final_brain, &other.final_brain), rng),
            energy: self.energy,
            signal: self.signal,
            connect_signal: 0,
            memory: self.memory,
            decision: self.decision.clone(),
        };
        //Perform unit mutations on offspring
        b.mutate(rng);
        b
    }

    pub fn divide(&mut self, rng: &mut R) -> Self {
        use mli::Genetic;
        //Divide energy in half when dividing
        self.energy /= 2;
        let mut b = Bot{
            bot_brain: self.bot_brain.clone(),
            node_brain: self.node_brain.clone(),
            final_brain: self.final_brain.clone(),
            energy: self.energy,
            signal: self.signal,
            connect_signal: 0,
            memory: self.memory,
            //Clone the rate of energy consumption in the decision
            decision: self.decision.clone(),
        };
        //Perform unit mutations on offspring
        b.mutate(rng);
        b
    }

    pub fn cycle(&mut self) {
        self.energy = self.energy.saturating_sub(EXISTENCE_COST);
        self.signal = self.decision.signal;
        self.connect_signal = self.decision.connect_signal;
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::io;
use std::str;
use byteorder::{LittleEndian, ReadBytesExt};
use chrono::{DateTime, Date, TimeZone, Local};

use fs::FatSharedStateRef;
use file::FatFile;

bitflags! {
    pub struct FatFileAttributes: u8 {
        const READ_ONLY  = 0x01;
        const HIDDEN     = 0x02;
        const SYSTEM     = 0x04;
        const VOLUME_ID  = 0x08;
        const DIRECTORY  = 0x10;
        const ARCHIVE    = 0x20;
        const LFN        = Self::READ_ONLY.bits | Self::HIDDEN.bits
                         | Self::SYSTEM.bits | Self::VOLUME_ID.bits;
    }
}

#[allow(dead_code)]
pub struct FatDirEntry {
    name: [u8; 11],
    attrs: FatFileAttributes,
    reserved_0: u8,
    create_time_0: u8,
    create_time_1: u16,
    create_date: u16,
    access_date: u16,
    first_cluster_hi: u16,
    modify_time: u16,
    modify_date: u16,
    first_cluster_lo: u16,
    size: u32,
    state: FatSharedStateRef,
}

fn convert_date(dos_date: u16) -> Date<Local> {
    let (year, month, day) = ((dos_date >> 9) + 1980, (dos_date >> 5) & 0xF, dos_date & 0x1F);
    Local.ymd(year as i32, month as u32, day as u32)
}

fn convert_date_time(dos_date: u16, dos_time: u16) -> DateTime<Local> {
    let (hour, min, sec) = (dos_time >> 11, (dos_time >> 5) & 0x3F, (dos_time & 0x1F) * 2);
    convert_date(dos_date).and_hms(hour as u32, min as u32, sec as u32)
}

impl FatDirEntry {

    pub fn get_name(&self) -> String {
        str::from_utf8(&self.name).unwrap().trim_right().to_string()
    }

    pub fn get_attrs(&self) -> FatFileAttributes {
        self.attrs
    }

    pub fn get_cluster(&self) -> u32 {
        ((self.first_cluster_hi as u32) << 16) | self.first_cluster_lo as u32
    }

    pub fn get_file(&self) -> FatFile {
        FatFile::new(self.get_cluster(), self.size, self.state.clone())
    }

    pub fn get_size(&self) -> u32 {
        self.size
    }

    pub fn get_create_time(&self) -> DateTime<Local> {
        convert_date_time(self.create_date, self.create_time_1)
    }

    pub fn get_access_date(&self) -> Date<Local> {
        convert_date(self.access_date)
    }

    pub fn get_modify_time(&self) -> DateTime<Local> {
        convert_date_time(self.modify_date, self.modify_time)
    }
}

pub struct FatDir {
    rdr: Box<Read>,
    state: FatSharedStateRef,
}

impl FatDir {

    pub(crate) fn new(rdr: Box<Read>, state: FatSharedStateRef) -> FatDir {
        FatDir { rdr, state }
    }

    pub fn list(&mut self) -> io::Result<Vec<FatDirEntry>> {
        let mut entries = Vec::new();
        loop {
            let entry = self.read_dir_entry()?;
            if entry.name[0] == 0 {
                break; // end of dir
            }
            if entry.name[0] == 0xE5 {
                continue; // deleted
            }
            entries.push(entry);
        }

        Ok(entries)
    }

    fn read_dir_entry(&mut self) -> io::Result<FatDirEntry> {
        let mut name = [0; 11];
        self.rdr.read(&mut name)?;
        let attrs = FatFileAttributes::from_bits(self.rdr.read_u8()?).expect("invalid attributes");
        Ok(FatDirEntry {
            name,
            attrs,
            reserved_0:       self.rdr.read_u8()?,
            create_time_0:    self.rdr.read_u8()?,
            create_time_1:    self.rdr.read_u16::<LittleEndian>()?,
            create_date:      self.rdr.read_u16::<LittleEndian>()?,
            access_date:      self.rdr.read_u16::<LittleEndian>()?,
            first_cluster_hi: self.rdr.read_u16::<LittleEndian>()?,
            modify_time:      self.rdr.read_u16::<LittleEndian>()?,
            modify_date:      self.rdr.read_u16::<LittleEndian>()?,
            first_cluster_lo: self.rdr.read_u16::<LittleEndian>()?,
            size:             self.rdr.read_u32::<LittleEndian>()?,
            state:            self.state.clone(),
        })
    }
}
<commit_msg>Ignore LFN and fix handling of extension in filename.<commit_after>use std::io::prelude::*;
use std::io;
use std::str;
use byteorder::{LittleEndian, ReadBytesExt};
use chrono::{DateTime, Date, TimeZone, Local};

use fs::FatSharedStateRef;
use file::FatFile;

bitflags! {
    pub struct FatFileAttributes: u8 {
        const READ_ONLY  = 0x01;
        const HIDDEN     = 0x02;
        const SYSTEM     = 0x04;
        const VOLUME_ID  = 0x08;
        const DIRECTORY  = 0x10;
        const ARCHIVE    = 0x20;
        const LFN        = Self::READ_ONLY.bits | Self::HIDDEN.bits
                         | Self::SYSTEM.bits | Self::VOLUME_ID.bits;
    }
}

#[allow(dead_code)]
pub struct FatDirEntry {
    name: [u8; 11],
    attrs: FatFileAttributes,
    reserved_0: u8,
    create_time_0: u8,
    create_time_1: u16,
    create_date: u16,
    access_date: u16,
    first_cluster_hi: u16,
    modify_time: u16,
    modify_date: u16,
    first_cluster_lo: u16,
    size: u32,
    state: FatSharedStateRef,
}

fn convert_date(dos_date: u16) -> Date<Local> {
    let (year, month, day) = ((dos_date >> 9) + 1980, (dos_date >> 5) & 0xF, dos_date & 0x1F);
    Local.ymd(year as i32, month as u32, day as u32)
}

fn convert_date_time(dos_date: u16, dos_time: u16) -> DateTime<Local> {
    let (hour, min, sec) = (dos_time >> 11, (dos_time >> 5) & 0x3F, (dos_time & 0x1F) * 2);
    convert_date(dos_date).and_hms(hour as u32, min as u32, sec as u32)
}

impl FatDirEntry {

    pub fn get_name(&self) -> String {
        let name = str::from_utf8(&self.name[0..8]).unwrap().trim_right();
        let ext = str::from_utf8(&self.name[8..11]).unwrap().trim_right();
        if ext == "" { name.to_string() } else { format!("{}.{}", name, ext) }
    }

    pub fn get_attrs(&self) -> FatFileAttributes {
        self.attrs
    }

    pub fn get_cluster(&self) -> u32 {
        ((self.first_cluster_hi as u32) << 16) | self.first_cluster_lo as u32
    }

    pub fn get_file(&self) -> FatFile {
        FatFile::new(self.get_cluster(), self.size, self.state.clone())
    }

    pub fn get_size(&self) -> u32 {
        self.size
    }

    pub fn get_create_time(&self) -> DateTime<Local> {
        convert_date_time(self.create_date, self.create_time_1)
    }

    pub fn get_access_date(&self) -> Date<Local> {
        convert_date(self.access_date)
    }

    pub fn get_modify_time(&self) -> DateTime<Local> {
        convert_date_time(self.modify_date, self.modify_time)
    }
}

pub struct FatDir {
    rdr: Box<Read>,
    state: FatSharedStateRef,
}

impl FatDir {

    pub(crate) fn new(rdr: Box<Read>, state: FatSharedStateRef) -> FatDir {
        FatDir { rdr, state }
    }

    pub fn list(&mut self) -> io::Result<Vec<FatDirEntry>> {
        let mut entries = Vec::new();
        loop {
            let entry = self.read_dir_entry()?;
            if entry.name[0] == 0 {
                break; // end of dir
            }
            if entry.name[0] == 0xE5 {
                continue; // deleted
            }
            if entry.attrs == FatFileAttributes::LFN {
                continue; // FIXME: support LFN
            }
            entries.push(entry);
        }

        Ok(entries)
    }

    fn read_dir_entry(&mut self) -> io::Result<FatDirEntry> {
        let mut name = [0; 11];
        self.rdr.read(&mut name)?;
        let attrs = FatFileAttributes::from_bits(self.rdr.read_u8()?).expect("invalid attributes");
        Ok(FatDirEntry {
            name,
            attrs,
            reserved_0:       self.rdr.read_u8()?,
            create_time_0:    self.rdr.read_u8()?,
            create_time_1:    self.rdr.read_u16::<LittleEndian>()?,
            create_date:      self.rdr.read_u16::<LittleEndian>()?,
            access_date:      self.rdr.read_u16::<LittleEndian>()?,
            first_cluster_hi: self.rdr.read_u16::<LittleEndian>()?,
            modify_time:      self.rdr.read_u16::<LittleEndian>()?,
            modify_date:      self.rdr.read_u16::<LittleEndian>()?,
            first_cluster_lo: self.rdr.read_u16::<LittleEndian>()?,
            size:             self.rdr.read_u32::<LittleEndian>()?,
            state:            self.state.clone(),
        })
    }
}
<|endoftext|>


<commit_before>pub use self::imp::*;

#[cfg(not(cross_platform_docs))]
mod imp {
    pub use core::option::Option;
    pub use core::clone::Clone;
    pub use core::marker::Copy;
    pub use core::mem;
}

#[cfg(cross_platform_docs)]
mod imp {
    pub enum Option<T> {
        Some(T),
        None,
    }
    impl<T: Copy> Copy for Option<T> {}
    impl<T: Clone> Clone for Option<T> {
        fn clone(&self) -> Option<T> { loop {} }
    }

    impl<T> Copy for *mut T {}
    impl<T> Clone for *mut T {
        fn clone(&self) -> *mut T { loop {} }
    }

    impl<T> Copy for *const T {}
    impl<T> Clone for *const T {
        fn clone(&self) -> *const T { loop {} }
    }

    pub trait Clone {
        fn clone(&self) -> Self;
    }

    #[lang = "copy"]
    pub trait Copy {}

    #[lang = "freeze"]
    pub trait Freeze {}

    #[lang = "sync"]
    pub trait Sync {}
    impl<T> Sync for T {}

    #[lang = "sized"]
    pub trait Sized {}

    macro_rules! each_int {
        ($mac:ident) => (
            $mac!(u8);
            $mac!(u16);
            $mac!(u32);
            $mac!(u64);
            $mac!(usize);
            each_signed_int!($mac);
        )
    }

    macro_rules! each_signed_int {
        ($mac:ident) => (
            $mac!(i8);
            $mac!(i16);
            $mac!(i32);
            $mac!(i64);
            $mac!(isize);
        )
    }

    #[lang = "div"]
    pub trait Div<RHS=Self> {
        type Output;
        fn div(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "shl"]
    pub trait Shl<RHS=Self> {
        type Output;
        fn shl(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "mul"]
    pub trait Mul<RHS=Self> {
        type Output;
        fn mul(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "sub"]
    pub trait Sub<RHS=Self> {
        type Output;
        fn sub(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "bitor"]
    pub trait Bitor<RHS=Self> {
        type Output;
        fn bitor(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "neg"]
    pub trait Neg {
        type Output;
        fn neg(self) -> Self::Output;
    }

    #[lang = "not"]
    pub trait Not {
        type Output;
        fn not(self) -> Self::Output;
    }

    #[lang = "add"]
    pub trait Add<RHS = Self> {
        type Output;
        fn add(self, r: RHS) -> Self::Output;
    }

    macro_rules! impl_traits {
        ($($i:ident)*) => ($(
            impl Div<$i> for $i {
                type Output = $i;
                fn div(self, rhs: $i) -> $i { self / rhs }
            }
            impl Shl<$i> for $i {
                type Output = $i;
                fn shl(self, rhs: $i) -> $i { self << rhs }
            }
            impl Mul for $i {
                type Output = $i;
                fn mul(self, rhs: $i) -> $i { self * rhs }
            }

            impl Sub for $i {
                type Output = $i;
                fn sub(self, rhs: $i) -> $i { self - rhs }
            }
            impl Bitor for $i {
                type Output = $i;
                fn bitor(self, rhs: $i) -> $i { self | rhs }
            }
            impl Neg for $i {
                type Output = $i;
                fn neg(self) -> $i { -self }
            }
            impl Not for $i {
                type Output = $i;
                fn not(self) -> $i { !self }
            }
            impl Add<$i> for $i {
                type Output = $i;
                fn add(self, other: $i) -> $i { self + other }
            }
            impl Copy for $i {}
            impl Clone for $i {
                fn clone(&self) -> $i { loop {} }
            }
        )*)
    }
    each_int!(impl_traits);

    pub mod mem {
        pub fn size_of_val<T>(_: &T) -> usize { 4 }
        pub fn size_of<T>() -> usize { 4 }
    }
}
<commit_msg>Auto merge of #1007 - canndrew:dox-traits, r=alexcrichton<commit_after>pub use self::imp::*;

#[cfg(not(cross_platform_docs))]
mod imp {
    pub use core::option::Option;
    pub use core::clone::Clone;
    pub use core::marker::Copy;
    pub use core::mem;
}

#[cfg(cross_platform_docs)]
mod imp {
    pub enum Option<T> {
        Some(T),
        None,
    }
    impl<T: Copy> Copy for Option<T> {}
    impl<T: Clone> Clone for Option<T> {
        fn clone(&self) -> Option<T> { loop {} }
    }

    impl<T> Copy for *mut T {}
    impl<T> Clone for *mut T {
        fn clone(&self) -> *mut T { loop {} }
    }

    impl<T> Copy for *const T {}
    impl<T> Clone for *const T {
        fn clone(&self) -> *const T { loop {} }
    }

    pub trait Clone {
        fn clone(&self) -> Self;
    }

    #[lang = "copy"]
    pub trait Copy {}

    #[lang = "freeze"]
    pub trait Freeze {}

    #[lang = "sync"]
    pub trait Sync {}
    impl<T> Sync for T {}

    #[lang = "sized"]
    pub trait Sized {}

    macro_rules! each_int {
        ($mac:ident) => (
            $mac!(u8);
            $mac!(u16);
            $mac!(u32);
            $mac!(u64);
            $mac!(usize);
            each_signed_int!($mac);
        )
    }

    macro_rules! each_signed_int {
        ($mac:ident) => (
            $mac!(i8);
            $mac!(i16);
            $mac!(i32);
            $mac!(i64);
            $mac!(isize);
        )
    }

    #[lang = "div"]
    pub trait Div<RHS=Self> {
        type Output;
        fn div(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "shl"]
    pub trait Shl<RHS=Self> {
        type Output;
        fn shl(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "mul"]
    pub trait Mul<RHS=Self> {
        type Output;
        fn mul(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "sub"]
    pub trait Sub<RHS=Self> {
        type Output;
        fn sub(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "bitand"]
    pub trait BitAnd<RHS=Self> {
        type Output;
        fn bitand(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "bitand_assign"]
    pub trait BitAndAssign<RHS = Self> {
        fn bitand_assign(&mut self, rhs: RHS);
    }

    #[lang = "bitor"]
    pub trait BitOr<RHS=Self> {
        type Output;
        fn bitor(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "bitor_assign"]
    pub trait BitOrAssign<RHS = Self> {
        fn bitor_assign(&mut self, rhs: RHS);
    }

    #[lang = "bitxor"]
    pub trait BitXor<RHS=Self> {
        type Output;
        fn bitxor(self, rhs: RHS) -> Self::Output;
    }

    #[lang = "bitxor_assign"]
    pub trait BitXorAssign<RHS = Self> {
        fn bitxor_assign(&mut self, rhs: RHS);
    }

    #[lang = "neg"]
    pub trait Neg {
        type Output;
        fn neg(self) -> Self::Output;
    }

    #[lang = "not"]
    pub trait Not {
        type Output;
        fn not(self) -> Self::Output;
    }

    #[lang = "add"]
    pub trait Add<RHS = Self> {
        type Output;
        fn add(self, r: RHS) -> Self::Output;
    }

    macro_rules! impl_traits {
        ($($i:ident)*) => ($(
            impl Div<$i> for $i {
                type Output = $i;
                fn div(self, rhs: $i) -> $i { self / rhs }
            }
            impl Shl<$i> for $i {
                type Output = $i;
                fn shl(self, rhs: $i) -> $i { self << rhs }
            }
            impl Mul for $i {
                type Output = $i;
                fn mul(self, rhs: $i) -> $i { self * rhs }
            }

            impl Sub for $i {
                type Output = $i;
                fn sub(self, rhs: $i) -> $i { self - rhs }
            }
            impl BitAnd for $i {
                type Output = $i;
                fn bitand(self, rhs: $i) -> $i { self & rhs }
            }
            impl BitAndAssign for $i {
                fn bitand_assign(&mut self, rhs: $i) { *self &= rhs; }
            }
            impl BitOr for $i {
                type Output = $i;
                fn bitor(self, rhs: $i) -> $i { self | rhs }
            }
            impl BitOrAssign for $i {
                fn bitor_assign(&mut self, rhs: $i) { *self |= rhs; }
            }
            impl BitXor for $i {
                type Output = $i;
                fn bitxor(self, rhs: $i) -> $i { self ^ rhs }
            }
            impl BitXorAssign for $i {
                fn bitxor_assign(&mut self, rhs: $i) { *self ^= rhs; }
            }
            impl Neg for $i {
                type Output = $i;
                fn neg(self) -> $i { -self }
            }
            impl Not for $i {
                type Output = $i;
                fn not(self) -> $i { !self }
            }
            impl Add<$i> for $i {
                type Output = $i;
                fn add(self, other: $i) -> $i { self + other }
            }
            impl Copy for $i {}
            impl Clone for $i {
                fn clone(&self) -> $i { loop {} }
            }
        )*)
    }
    each_int!(impl_traits);

    pub mod mem {
        pub fn size_of_val<T>(_: &T) -> usize { 4 }
        pub fn size_of<T>() -> usize { 4 }
    }
}
<|endoftext|>


<commit_before>use atom::*;
use symbol;
use errors::*;
use std::fmt;
use std::rc::Rc;
use std::cell::RefCell;

#[derive (Debug, Clone, PartialEq)]
struct Entry {
    key: symbol::InternedStr,
    value: Atom,
}

impl fmt::Display for Entry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} => {}", self.key, self.value)
    }
}

#[derive(Debug,PartialEq)]
struct EnvGeneration {
    value: Vec<Entry>,
    parent: Option<Env>,
}

impl fmt::Display for EnvGeneration {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "EnvGeneration[{:p}]", self));
        for i in &self.value {
            try!(write!(f, "\t{}", i));
        }
        Ok(())
    }
}

impl EnvGeneration {
    fn new(parent: Option<Env>) -> EnvGeneration {
        EnvGeneration {
            value: Vec::new(),
            parent: parent,
        }
    }

    fn find(&self, key: &str) -> Option<&Entry> {
        self.value.iter().rev().find(|entry| entry.key.as_ref() == key)
    }
}

#[derive (Debug, Clone, PartialEq)]
pub struct Env(Rc<RefCell<EnvGeneration>>);

impl Default for Env {
    fn default() -> Env {
        Env::new(None)
    }
}

impl fmt::Display for Env {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let gen = self.0.borrow();
        try!(write!(f, "Top-level: EnvGeneration: {}\n", *gen));

        if let Some(ref parent) = gen.parent {
            try!(write!(f, "parent: {}\n", parent));
        } else {
            try!(write!(f, "no parent\n"));
        }
        Ok(())
    }
}

impl Env {
    pub fn new(parent: Option<Env>) -> Env {
        Env(Rc::new(RefCell::new(EnvGeneration::new(parent))))
    }

    fn find(&self, key: &str) -> Option<Atom> {
        let gen = self.0.borrow();
        let value = &gen.value;
        match value.iter().rev().find(|entry| entry.key.as_ref() == key) {
            Some(ref entry) => Some(entry.value.clone()),
            None => {
                if let Some(ref parent) = gen.parent {
                    parent.find(key)
                } else {
                    None
                }
            }
        }
    }

    pub fn bind_mut(&mut self, params: &[Atom], args: &[Atom]) {
        let mut params_iter = params.iter();
        let mut args_iter = args.iter();
        while let Some(&Atom::Symbol(ref sym)) = params_iter.next() {
            if sym.as_ref() == "&" {
                if let Some(&Atom::Symbol(ref splat)) = params_iter.next() {
                    let vals = args_iter.cloned().collect();
                    self.0.borrow_mut().value.push(Entry {
                        key: *splat,
                        value: Atom::list(vals),
                    });
                    break;
                }
            } else {
                let arg = args_iter.next().cloned().unwrap_or(Atom::Nil);

                self.0.borrow_mut().value.push(Entry {
                    key: *sym,
                    value: arg,
                });
            }
        }
    }

    pub fn bind(&mut self, params: &[Atom], args: &[Atom]) -> Env {
        let mut arg_map = Vec::with_capacity(params.len());
        let mut params_iter = params.iter();
        let mut args_iter = args.iter();

        while let Some(&Atom::Symbol(ref sym)) = params_iter.next() {
            if sym.as_ref() == "&" {
                if let Some(&Atom::Symbol(ref splat)) = params_iter.next() {
                    let vals = args_iter.cloned().collect();
                    arg_map.push(Entry {
                        key: *splat,
                        value: Atom::list(vals),
                    });
                    break;
                }
            } else {
                let arg = args_iter.next().cloned().unwrap_or(Atom::Nil);

                self.0.borrow_mut().value.push(Entry {
                    key: *sym,
                    value: arg,
                });
            }
        }

        let env_gen = EnvGeneration {
            value: arg_map,
            parent: Some(self.clone()),
        };
        Env(Rc::new(RefCell::new(env_gen)))
    }

    pub fn get(&self, key: &str) -> Option<Atom> {
        self.find(key)
    }

    pub fn define(&mut self, key: symbol::InternedStr, value: Atom) -> Result<Atom, Error> {
        if let Some(_) = self.0.borrow().find(key.as_ref()) {
            // println!("env is: {}", self);
            return Err(invalid_arg(&format!("define has entry already: {}", key.as_ref())));
        }
        self.0.borrow_mut().value.push(Entry {
            key: key,
            value: value,
        });
        Ok(Atom::Symbol(key))
    }

    pub fn set(&mut self, key: symbol::InternedStr, value: Atom) -> Result<Atom, Error> {
        {
            // set in current generation
            let mut gen = self.0.borrow_mut();
            if let Some(mut entry) = gen.value.iter_mut().find(|entry| entry.key == key) {
                entry.value = value;
                return Ok(Atom::Symbol(key));
            }
        }

        if let Some(ref mut parent) = self.0.borrow_mut().parent {
            parent.set(key, value)
        } else {
            Err(invalid_arg("in set"))
        }
    }
}

#[cfg(test)]
mod tests {
    use self::super::*;
    use atom::*;
    use errors::*;
    use symbol::*;

    #[test]
    fn nested_get() {
        let mut env = Env::new(None);

        env.define(intern("foo"), Atom::String("bar".to_owned())).unwrap();

        let env2 = Env::new(Some(env.clone()));

        assert_eq!(Atom::String("bar".to_owned()),
                   env2.get(intern("foo").as_ref()).unwrap());
    }

    #[test]
    fn splat() {
        let mut env = Env::new(None);

        let params = vec![Atom::symbol("&"), Atom::symbol("body")];

        let e = env.bind(&params, &vec![Atom::from(0), Atom::from(1), Atom::from(2)]);

        let body = e.get("body").unwrap();

        assert_eq!(Atom::list(vec![Atom::from(0), Atom::from(1), Atom::from(2)]),
                   body);
    }

    #[test]
    fn define() {
        let mut env = Env::new(None);

        env.define(intern("foo"), Atom::string("bar")).unwrap();

        if let Err(Error::InvalidArguments(_)) = env.set(intern("bar"), Atom::string("foo")) {
            assert!(true);
        } else {
            assert!(false);
        }

        let mut env2 = Env::new(Some(env.clone()));

        env2.set(intern("foo"), Atom::parse("0")).unwrap();

        assert_eq!(Atom::parse("0"), env.get("foo").unwrap());
        assert_eq!(Atom::parse("0"), env2.get("foo").unwrap());

        env2.define(intern("foo"), Atom::string("baz")).unwrap();

        assert_eq!(Atom::string("baz"), env2.get("foo").unwrap());
        assert_eq!(Atom::parse("0"), env.get("foo").unwrap());
    }

}
<commit_msg>mutable borrows now shouldn't grow unbounded<commit_after>use atom::*;
use symbol;
use errors::*;
use std::fmt;
use std::rc::Rc;
use std::cell::RefCell;

#[derive (Debug, Clone, PartialEq)]
struct Entry {
    key: symbol::InternedStr,
    value: Atom,
}

impl fmt::Display for Entry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} => {}", self.key, self.value)
    }
}

#[derive(Debug,PartialEq)]
struct EnvGeneration {
    value: Vec<Entry>,
    parent: Option<Env>,
}

impl fmt::Display for EnvGeneration {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "EnvGeneration[{:p}]", self));
        for i in &self.value {
            try!(write!(f, "\t{}", i));
        }
        Ok(())
    }
}

impl EnvGeneration {
    fn new(parent: Option<Env>) -> EnvGeneration {
        EnvGeneration {
            value: Vec::new(),
            parent: parent,
        }
    }

    fn find(&self, key: &str) -> Option<&Entry> {
        self.value.iter().rev().find(|entry| entry.key.as_ref() == key)
    }
}

#[derive (Debug, Clone, PartialEq)]
pub struct Env(Rc<RefCell<EnvGeneration>>);

impl Default for Env {
    fn default() -> Env {
        Env::new(None)
    }
}

impl fmt::Display for Env {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let gen = self.0.borrow();
        try!(write!(f, "Top-level: EnvGeneration: {}\n", *gen));

        if let Some(ref parent) = gen.parent {
            try!(write!(f, "parent: {}\n", parent));
        } else {
            try!(write!(f, "no parent\n"));
        }
        Ok(())
    }
}

impl Env {
    pub fn new(parent: Option<Env>) -> Env {
        Env(Rc::new(RefCell::new(EnvGeneration::new(parent))))
    }

    fn find(&self, key: &str) -> Option<Atom> {
        let gen = self.0.borrow();
        let value = &gen.value;
        match value.iter().rev().find(|entry| entry.key.as_ref() == key) {
            Some(ref entry) => Some(entry.value.clone()),
            None => {
                if let Some(ref parent) = gen.parent {
                    parent.find(key)
                } else {
                    None
                }
            }
        }
    }

    pub fn num_generations(&self) -> usize {
        self.num_gen(1)
    }

    fn num_gen(&self, c: usize) -> usize {
        let gen = self.0.borrow();
        if let Some(ref parent) = gen.parent {
            return parent.num_gen(c + 1)
        }
        else {
            c
        }
    }

    pub fn generation_size(&self) -> usize {
        self.0.borrow().value.len()
    }

    pub fn bind_mut(&mut self, params: &[Atom], args: &[Atom]) {
        let mut params_iter = params.iter();
        let mut args_iter = args.iter();
        while let Some(&Atom::Symbol(ref sym)) = params_iter.next() {
            if sym.as_ref() == "&" {
                if let Some(&Atom::Symbol(ref splat)) = params_iter.next() {
                    let vals = args_iter.cloned().collect();
                    self.0.borrow_mut().value.push(Entry {
                        key: *splat,
                        value: Atom::list(vals),
                    });
                    break;
                }
            } else {
                let arg = args_iter.next().cloned().unwrap_or(Atom::Nil);

                {
                    // tricking the borrow checker here
                    let mut gen = self.0.borrow_mut();

                    if let Some(mut entry) = gen.value.iter_mut().find(|entry| entry.key == *sym) {
                        entry.value = arg;
                        continue;
                    }
                }

                self.0.borrow_mut().value.push(Entry {
                    key: *sym,
                    value: arg,
                });
            }
        }
    }

    pub fn bind(&mut self, params: &[Atom], args: &[Atom]) -> Env {
        let mut arg_map = Vec::with_capacity(params.len());
        let mut params_iter = params.iter();
        let mut args_iter = args.iter();

        while let Some(&Atom::Symbol(ref sym)) = params_iter.next() {
            if sym.as_ref() == "&" {
                if let Some(&Atom::Symbol(ref splat)) = params_iter.next() {
                    let vals = args_iter.cloned().collect();
                    arg_map.push(Entry {
                        key: *splat,
                        value: Atom::list(vals),
                    });
                    break;
                }
            } else {
                let arg = args_iter.next().cloned().unwrap_or(Atom::Nil);

                self.0.borrow_mut().value.push(Entry {
                    key: *sym,
                    value: arg,
                });
            }
        }

        let env_gen = EnvGeneration {
            value: arg_map,
            parent: Some(self.clone()),
        };
        Env(Rc::new(RefCell::new(env_gen)))
    }

    pub fn get(&self, key: &str) -> Option<Atom> {
        self.find(key)
    }

    pub fn define(&mut self, key: symbol::InternedStr, value: Atom) -> Result<Atom, Error> {
        if let Some(_) = self.0.borrow().find(key.as_ref()) {
            // println!("env is: {}", self);
            return Err(invalid_arg(&format!("define has entry already: {}", key.as_ref())));
        }
        self.0.borrow_mut().value.push(Entry {
            key: key,
            value: value,
        });
        Ok(Atom::Symbol(key))
    }

    pub fn set(&mut self, key: symbol::InternedStr, value: Atom) -> Result<Atom, Error> {
        {
            // set in current generation
            let mut gen = self.0.borrow_mut();
            if let Some(mut entry) = gen.value.iter_mut().find(|entry| entry.key == key) {
                entry.value = value;
                return Ok(Atom::Symbol(key));
            }
        }

        if let Some(ref mut parent) = self.0.borrow_mut().parent {
            parent.set(key, value)
        } else {
            Err(invalid_arg("in set"))
        }
    }
}

#[cfg(test)]
mod tests {
    use self::super::*;
    use atom::*;
    use errors::*;
    use symbol::*;

    #[test]
    fn nested_get() {
        let mut env = Env::new(None);

        env.define(intern("foo"), Atom::String("bar".to_owned())).unwrap();

        let env2 = Env::new(Some(env.clone()));

        assert_eq!(Atom::String("bar".to_owned()),
                   env2.get(intern("foo").as_ref()).unwrap());
    }

    #[test]
    fn splat() {
        let mut env = Env::new(None);

        let params = vec![Atom::symbol("&"), Atom::symbol("body")];

        let e = env.bind(&params, &vec![Atom::from(0), Atom::from(1), Atom::from(2)]);

        let body = e.get("body").unwrap();

        assert_eq!(Atom::list(vec![Atom::from(0), Atom::from(1), Atom::from(2)]),
                   body);
    }

    #[test]
    fn define() {
        let mut env = Env::new(None);

        env.define(intern("foo"), Atom::string("bar")).unwrap();

        if let Err(Error::InvalidArguments(_)) = env.set(intern("bar"), Atom::string("foo")) {
            assert!(true);
        } else {
            assert!(false);
        }

        let mut env2 = Env::new(Some(env.clone()));

        env2.set(intern("foo"), Atom::parse("0")).unwrap();

        assert_eq!(Atom::parse("0"), env.get("foo").unwrap());
        assert_eq!(Atom::parse("0"), env2.get("foo").unwrap());

        env2.define(intern("foo"), Atom::string("baz")).unwrap();

        assert_eq!(Atom::string("baz"), env2.get("foo").unwrap());
        assert_eq!(Atom::parse("0"), env.get("foo").unwrap());
    }

    #[test]
    fn bind_mut() {
        let mut env = Env::default();
        let args = vec![Atom::from(0), Atom::from(1)];
        let params = vec![Atom::symbol("a"), Atom::symbol("b")];
        env.bind_mut(&params, &args);

        assert_eq!(env.get("a").unwrap(), Atom::from(0));
        assert_eq!(env.get("b").unwrap(), Atom::from(1));

        env.bind_mut(&params, &vec![Atom::from(2), Atom::from(42)]);

        assert_eq!(env.get("a").unwrap(), Atom::from(2));
        assert_eq!(env.get("b").unwrap(), Atom::from(42));

        assert_eq!(2, env.generation_size());
    }

}
<|endoftext|>