<commit_before>pub mod ffi {
   #![allow(non_upper_case_globals)]

   pub use libc::{
      c_char, c_int, c_uint, c_long, c_ulong, c_void
   };
   use std::mem;
   use ::os::xcb::ffi::xcb_connection_t;

   pub enum XDisplay { }
   pub enum XPrivate { }
   pub enum XrmHashBucketRec { }
   pub enum XGC { }

   pub type XID = c_ulong;
   pub type GC = *mut XGC;
   pub type Display = XDisplay;
   pub type Colormap = XID;
   pub type Window = XID;
   pub type XPointer = *mut c_char;
   pub type VisualID = c_ulong;

   pub type XEventQueueOwner = c_uint;

   pub const XlibOwnsEventQueue: c_uint = 0;
   pub const XCBOwnsEventQueue: c_uint = 1;

   #[repr(C)]
   #[derive(Copy)]
   pub struct XExtData {
      pub number: c_int,
      pub next: *mut XExtData,
      pub free_private: Option<extern "C" fn(extension: *mut XExtData) -> c_int>,
      pub private_data: XPointer,
   }
   impl Clone for XExtData {
      fn clone(&self) -> Self { *self }
   }
   impl Default for XExtData {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Visual {
      pub ext_data: *mut XExtData,
      pub visualid: VisualID,
      pub class: c_int,
      pub red_mask: c_ulong,
      pub green_mask: c_ulong,
      pub blue_mask: c_ulong,
      pub bits_per_rgb: c_int,
      pub map_entries: c_int,
   }
   impl Clone for Visual {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Visual {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Depth {
      pub depth: c_int,
      pub nvisuals: c_int,
      pub visuals: *mut Visual,
   }
   impl Clone for Depth {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Depth {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Screen {
      pub ext_data: *mut XExtData,
      pub display: *mut XDisplay,
      pub root: Window,
      pub width: c_int,
      pub height: c_int,
      pub mwidth: c_int,
      pub mheight: c_int,
      pub ndepths: c_int,
      pub depths: *mut Depth,
      pub root_depth: c_int,
      pub root_visual: *mut Visual,
      pub default_gc: GC,
      pub cmap: Colormap,
      pub white_pixel: c_ulong,
      pub black_pixel: c_ulong,
      pub max_maps: c_int,
      pub min_maps: c_int,
      pub backing_store: c_int,
      pub save_unders: c_int,
      pub root_input_mask: c_long,
   }
   impl Clone for Screen {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Screen {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct ScreenFormat {
      pub ext_data: *mut XExtData,
      pub depth: c_int,
      pub bits_per_pixel: c_int,
      pub scanline_pad: c_int,
   }
   impl Clone for ScreenFormat {
      fn clone(&self) -> Self { *self }
   }
   impl Default for ScreenFormat {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct XPrivDisplay {
      pub ext_data: *mut XExtData,
      pub private1: *mut XPrivate,
      pub fd: c_int,
      pub private2: c_int,
      pub proto_major_version: c_int,
      pub proto_minor_version: c_int,
      pub vendor: *mut c_char,
      pub private3: XID,
      pub private4: XID,
      pub private5: XID,
      pub private6: c_int,
      pub resource_alloc: Option<extern "C" fn(arg1: *mut XDisplay) -> XID>,
      pub byte_order: c_int,
      pub bitmap_unit: c_int,
      pub bitmap_pad: c_int,
      pub bitmap_bit_order: c_int,
      pub nformats: c_int,
      pub pixmap_format: *mut ScreenFormat,
      pub private8: c_int,
      pub release: c_int,
      pub private9: *mut XPrivate,
      pub private10: *mut XPrivate,
      pub qlen: c_int,
      pub last_request_read: c_ulong,
      pub request: c_ulong,
      pub private11: XPointer,
      pub private12: XPointer,
      pub private13: XPointer,
      pub private14: XPointer,
      pub max_request_size: c_uint,
      pub db: *mut XrmHashBucketRec,
      pub private15: Option<extern "C" fn(arg1: *mut XDisplay) -> c_int>,
      pub display_name: *mut c_char,
      pub default_screen: c_int,
      pub nscreens: c_int,
      pub screens: *mut Screen,
      pub motion_buffer: c_ulong,
      pub private16: c_ulong,
      pub min_keycode: c_int,
      pub max_keycode: c_int,
      pub private17: XPointer,
      pub private18: XPointer,
      pub private19: c_int,
      pub xdefaults: *mut c_char,
   }
   impl Clone for XPrivDisplay {
      fn clone(&self) -> Self { *self }
   }
   impl Default for XPrivDisplay {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }
   pub type _XPrivDisplay = *mut XPrivDisplay;

   #[link(name="X11")]
   extern "C" {
      pub fn XOpenDisplay(display_name: *const c_char) -> *mut Display;
      pub fn XCloseDisplay(display: *mut Display) -> c_int;
      pub fn XFree(data: *mut c_void) -> c_int;
   }

   #[link(name="X11-xcb")]
   extern "C" {
      pub fn XGetXCBConnection(
         display: *mut Display
      ) -> *mut xcb_connection_t;

      pub fn XSetEventQueueOwner(
         display: *mut Display,
         owner: XEventQueueOwner
      ) -> ();
   }
}

use std::ptr;
use std::ffi::{CString, CStr};

use libc::c_char;

use ::error::{RuntimeError, ErrorKind};
use ::os::xcb::Connection;

pub struct Display {
   pub ptr: *mut ffi::Display
}

impl Display {
   pub fn default() -> Result<Self, RuntimeError> {
      Display::from_ptr(ptr::null())
   }

   pub fn new<T: Into<Vec<u8>>>(name: T) -> Result<Self, RuntimeError> {
      let c_name = try!(CString::new(name.into()));

      Display::from_ptr(c_name.as_ptr())
   }

   fn from_ptr(name: *const c_char) -> Result<Self, RuntimeError> {
      let display_ptr = unsafe {
         ffi::XOpenDisplay(name)
      };

      if display_ptr.is_null() {
         let description = format!(
            "Opening X display '{}' failed",
            unsafe { CStr::from_ptr(name).to_str().unwrap() }
         );
         return Err(RuntimeError::new(
            ErrorKind::Xlib,
            description
         ));
      }

      Ok(
         Display {
            ptr: display_ptr
         }
      )
   }

   pub fn xcb_connection(self: &Self) -> Result<Connection, RuntimeError> {
      let connection = unsafe {
         ffi::XGetXCBConnection(self.ptr)
      };
      if connection.is_null() {
         return Err(RuntimeError::new(
            ErrorKind::Xlib,
            "Getting XCB connection from display failed".to_string()
         ));
      }

      Ok(
         Connection::new(connection)
      )
   }

   pub fn xcb_own_event_queue(self: &Self) {
      unsafe {
         ffi::XSetEventQueueOwner(
            self.ptr,
            ffi::XCBOwnsEventQueue
         )
      };
   }

   #[inline]
   pub fn default_screen(&self) -> ffi::c_int {
      unsafe{
         (
            *(self.ptr as ffi::_XPrivDisplay)
         ).default_screen
      }
   }
}

impl Drop for Display {
   fn drop (&mut self) {
      unsafe {
         ffi::XCloseDisplay(self.ptr);
      }
   }
}

#[cfg(test)]
mod test {
   use std::env;
   use super::Display;

   #[test]
   fn test_create_display() {
      assert!(Display::default().is_ok());
   }

   #[test]
   fn test_create_display_from_env() {
      let name = env::var("DISPLAY").unwrap();
      assert!(Display::new(name).is_ok());
   }

   #[test]
   fn test_create_display_error_str() {
      assert!(Display::new("ErrorStringHere").is_err());
   }

   #[test]
   fn test_create_display_nul_str() {
      assert!(Display::new(&b"one\0two"[..]).is_err());
   }

   #[test]
   fn test_create_get_xcb_connection() {
      assert!(Display::default().unwrap().xcb_connection().is_ok());
   }
}

<commit_msg>Just &self<commit_after>pub mod ffi {
   #![allow(non_upper_case_globals)]

   pub use libc::{
      c_char, c_int, c_uint, c_long, c_ulong, c_void
   };
   use std::mem;
   use ::os::xcb::ffi::xcb_connection_t;

   pub enum XDisplay { }
   pub enum XPrivate { }
   pub enum XrmHashBucketRec { }
   pub enum XGC { }

   pub type XID = c_ulong;
   pub type GC = *mut XGC;
   pub type Display = XDisplay;
   pub type Colormap = XID;
   pub type Window = XID;
   pub type XPointer = *mut c_char;
   pub type VisualID = c_ulong;

   pub type XEventQueueOwner = c_uint;

   pub const XlibOwnsEventQueue: c_uint = 0;
   pub const XCBOwnsEventQueue: c_uint = 1;

   #[repr(C)]
   #[derive(Copy)]
   pub struct XExtData {
      pub number: c_int,
      pub next: *mut XExtData,
      pub free_private: Option<extern "C" fn(extension: *mut XExtData) -> c_int>,
      pub private_data: XPointer,
   }
   impl Clone for XExtData {
      fn clone(&self) -> Self { *self }
   }
   impl Default for XExtData {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Visual {
      pub ext_data: *mut XExtData,
      pub visualid: VisualID,
      pub class: c_int,
      pub red_mask: c_ulong,
      pub green_mask: c_ulong,
      pub blue_mask: c_ulong,
      pub bits_per_rgb: c_int,
      pub map_entries: c_int,
   }
   impl Clone for Visual {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Visual {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Depth {
      pub depth: c_int,
      pub nvisuals: c_int,
      pub visuals: *mut Visual,
   }
   impl Clone for Depth {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Depth {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Screen {
      pub ext_data: *mut XExtData,
      pub display: *mut XDisplay,
      pub root: Window,
      pub width: c_int,
      pub height: c_int,
      pub mwidth: c_int,
      pub mheight: c_int,
      pub ndepths: c_int,
      pub depths: *mut Depth,
      pub root_depth: c_int,
      pub root_visual: *mut Visual,
      pub default_gc: GC,
      pub cmap: Colormap,
      pub white_pixel: c_ulong,
      pub black_pixel: c_ulong,
      pub max_maps: c_int,
      pub min_maps: c_int,
      pub backing_store: c_int,
      pub save_unders: c_int,
      pub root_input_mask: c_long,
   }
   impl Clone for Screen {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Screen {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct ScreenFormat {
      pub ext_data: *mut XExtData,
      pub depth: c_int,
      pub bits_per_pixel: c_int,
      pub scanline_pad: c_int,
   }
   impl Clone for ScreenFormat {
      fn clone(&self) -> Self { *self }
   }
   impl Default for ScreenFormat {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct XPrivDisplay {
      pub ext_data: *mut XExtData,
      pub private1: *mut XPrivate,
      pub fd: c_int,
      pub private2: c_int,
      pub proto_major_version: c_int,
      pub proto_minor_version: c_int,
      pub vendor: *mut c_char,
      pub private3: XID,
      pub private4: XID,
      pub private5: XID,
      pub private6: c_int,
      pub resource_alloc: Option<extern "C" fn(arg1: *mut XDisplay) -> XID>,
      pub byte_order: c_int,
      pub bitmap_unit: c_int,
      pub bitmap_pad: c_int,
      pub bitmap_bit_order: c_int,
      pub nformats: c_int,
      pub pixmap_format: *mut ScreenFormat,
      pub private8: c_int,
      pub release: c_int,
      pub private9: *mut XPrivate,
      pub private10: *mut XPrivate,
      pub qlen: c_int,
      pub last_request_read: c_ulong,
      pub request: c_ulong,
      pub private11: XPointer,
      pub private12: XPointer,
      pub private13: XPointer,
      pub private14: XPointer,
      pub max_request_size: c_uint,
      pub db: *mut XrmHashBucketRec,
      pub private15: Option<extern "C" fn(arg1: *mut XDisplay) -> c_int>,
      pub display_name: *mut c_char,
      pub default_screen: c_int,
      pub nscreens: c_int,
      pub screens: *mut Screen,
      pub motion_buffer: c_ulong,
      pub private16: c_ulong,
      pub min_keycode: c_int,
      pub max_keycode: c_int,
      pub private17: XPointer,
      pub private18: XPointer,
      pub private19: c_int,
      pub xdefaults: *mut c_char,
   }
   impl Clone for XPrivDisplay {
      fn clone(&self) -> Self { *self }
   }
   impl Default for XPrivDisplay {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }
   pub type _XPrivDisplay = *mut XPrivDisplay;

   #[link(name="X11")]
   extern "C" {
      pub fn XOpenDisplay(display_name: *const c_char) -> *mut Display;
      pub fn XCloseDisplay(display: *mut Display) -> c_int;
      pub fn XFree(data: *mut c_void) -> c_int;
   }

   #[link(name="X11-xcb")]
   extern "C" {
      pub fn XGetXCBConnection(
         display: *mut Display
      ) -> *mut xcb_connection_t;

      pub fn XSetEventQueueOwner(
         display: *mut Display,
         owner: XEventQueueOwner
      ) -> ();
   }
}

use std::ptr;
use std::ffi::{CString, CStr};

use libc::c_char;

use ::error::{RuntimeError, ErrorKind};
use ::os::xcb::Connection;

pub struct Display {
   pub ptr: *mut ffi::Display
}

impl Display {
   pub fn default() -> Result<Self, RuntimeError> {
      Display::from_ptr(ptr::null())
   }

   pub fn new<T: Into<Vec<u8>>>(name: T) -> Result<Self, RuntimeError> {
      let c_name = try!(CString::new(name.into()));

      Display::from_ptr(c_name.as_ptr())
   }

   fn from_ptr(name: *const c_char) -> Result<Self, RuntimeError> {
      let display_ptr = unsafe {
         ffi::XOpenDisplay(name)
      };

      if display_ptr.is_null() {
         let description = format!(
            "Opening X display '{}' failed",
            unsafe { CStr::from_ptr(name).to_str().unwrap() }
         );
         return Err(RuntimeError::new(
            ErrorKind::Xlib,
            description
         ));
      }

      Ok(
         Display {
            ptr: display_ptr
         }
      )
   }

   pub fn xcb_connection(&self) -> Result<Connection, RuntimeError> {
      let connection = unsafe {
         ffi::XGetXCBConnection(self.ptr)
      };
      if connection.is_null() {
         return Err(RuntimeError::new(
            ErrorKind::Xlib,
            "Getting XCB connection from display failed".to_string()
         ));
      }

      Ok(
         Connection::new(connection)
      )
   }

   pub fn xcb_own_event_queue(&self) {
      unsafe {
         ffi::XSetEventQueueOwner(
            self.ptr,
            ffi::XCBOwnsEventQueue
         )
      };
   }

   #[inline]
   pub fn default_screen(&self) -> ffi::c_int {
      unsafe{
         (
            *(self.ptr as ffi::_XPrivDisplay)
         ).default_screen
      }
   }
}

impl Drop for Display {
   fn drop (&mut self) {
      unsafe {
         ffi::XCloseDisplay(self.ptr);
      }
   }
}

#[cfg(test)]
mod test {
   use std::env;
   use super::Display;

   #[test]
   fn test_create_display() {
      assert!(Display::default().is_ok());
   }

   #[test]
   fn test_create_display_from_env() {
      let name = env::var("DISPLAY").unwrap();
      assert!(Display::new(name).is_ok());
   }

   #[test]
   fn test_create_display_error_str() {
      assert!(Display::new("ErrorStringHere").is_err());
   }

   #[test]
   fn test_create_display_nul_str() {
      assert!(Display::new(&b"one\0two"[..]).is_err());
   }

   #[test]
   fn test_create_get_xcb_connection() {
      assert!(Display::default().unwrap().xcb_connection().is_ok());
   }
}

<|endoftext|>


<commit_before>use chrono::Local;
use ndarray::Array3;
use ordinal::Ordinal;
use rayon;
use std::fs::{copy, create_dir_all, File};
use std::io::Error;
use std::io::prelude::*;
use term_size;
use ansi_term::Colour::Blue;

use grid;

lazy_static! {
    /// Date & time at which the simulation was started. Used as a unique identifier for
    /// the output directory of a run.
    static ref PROJDATE: String = Local::now().format("%Y-%m-%d_%H:%M:%S").to_string();
}

/// Simply prints the Wafer banner with current commit info and thread count.
pub fn print_banner(sha: &str) {
    println!("                    {}", Blue.paint("___"));
    println!("   __      ____ _  {}__ _ __", Blue.paint("/ __\\"));
    println!("   \\ \\ /\\ / / _` |{} / _ \\ '__|", Blue.paint("/ /"));
    println!("    \\ V  V / (_| {}|  __/ |    Current build SHA1: {}",
             Blue.paint("/ _\\"),
             sha);
    println!("     \\_/\\_/ \\__,{}   \\___|_|    Parallel tasks running on {} threads.",
             Blue.paint("/ /"),
             rayon::current_num_threads());
    println!("              {}", Blue.paint("\\__/"));
    println!("");
}

/// Outputs the current potential to disk in a plain, csv format
///
/// # Arguments
/// *`v` - The potential to output
///
/// # Returns
/// * A result type with a `std::io::Error`. The result value is a true bool
/// as we really only want to error check the result.
pub fn potential_plain(v: &Array3<f64>, project: &str) -> Result<bool, Error> {
    let mut buffer = File::create(get_project_dir(project) + "/potential.csv")?;
    let dims = v.dim();
    let work = v.slice(s![3..(dims.0 as isize) - 3,
                          3..(dims.1 as isize) - 3,
                          3..(dims.2 as isize) - 3]);
    for ((i, j, k), el) in work.indexed_iter() {
        let output = format!("{}, {}, {}, {:e}\n", i, j, k, el);
        buffer.write_all(output.as_bytes())?;
    }
    Ok(true)
}

/// Outputs a wavefunction to disk in a plain, csv format
///
/// # Arguments
/// * `phi` - The wavefunction to output
/// * `num` - The wavefunction's excited state value for file naming.
/// * `converged` - a bool advising the state of the wavefunction. If false, the filename
/// will have `_partial` appended to it to indicate a restart is required.
///
/// # Returns
/// * A result type with a `std::io::Error`. The result value is a true bool
/// as we really only want to error check the result.
pub fn wavefunction_plain(phi: &Array3<f64>,
                          num: u8,
                          converged: bool,
                          project: &str)
                          -> Result<bool, Error> {
    let filename = format!("{}/wavefunction_{}{}.csv",
                           get_project_dir(project),
                           num,
                           if converged { "" } else { "_partial" });
    let mut buffer = File::create(filename)?;
    let dims = phi.dim();
    let work = phi.slice(s![3..(dims.0 as isize) - 3,
                            3..(dims.1 as isize) - 3,
                            3..(dims.2 as isize) - 3]);
    for ((i, j, k), el) in work.indexed_iter() {
        let output = format!("{}, {}, {}, {:e}\n", i, j, k, el);
        buffer.write_all(output.as_bytes())?;
    }
    Ok(true)
}

/// Pretty prints a header for the subsequent observable data
pub fn print_observable_header(wnum: u8) {
    let width = get_term_size();
    let spacer = (width - 69) / 2;
    let col2 = 37; //Energy+rrms+1
    println!("");
    if let 0 = wnum {
        println!("{:═^lspace$}╤{:═^twidth$}╤{:═^w$}╤{:═^width$}╤{:═^rspace$}",
                 "",
                 "",
                 " Ground state caclulation ",
                 "",
                 "",
                 twidth = 12,
                 width = 16,
                 w = col2,
                 lspace = spacer,
                 rspace = if 2 * spacer + 69 < width {
                     spacer + 1
                 } else {
                     spacer
                 });
    } else {
        println!("{:═^lspace$}╤{:═^twidth$}╤{:═^w$}╤{:═^width$}╤{:═^rspace$}",
                 "",
                 "",
                 format!(" {} excited state caclulation ", Ordinal::from(wnum)),
                 "",
                 "",
                 twidth = 12,
                 width = 16,
                 w = col2,
                 lspace = spacer,
                 rspace = if 2 * spacer + 69 < width {
                     spacer + 1
                 } else {
                     spacer
                 });
    }
    println!("{:^space$}│{:^twidth$}│{:^ewidth$}│{:^width$}│{:^width$}│",
             "",
             "Time (τ)",
             "Energy",
             "rᵣₘₛ",
             "Difference",
             twidth = 12,
             ewidth = 20,
             width = 16,
             space = spacer);
    println!("{:─^lspace$}┼{:─^twidth$}┼{:─^ewidth$}┼{:─^width$}┼{:─^width$}┼{:─^rspace$}",
             "",
             "",
             "",
             "",
             "",
             "",
             twidth = 12,
             ewidth = 20,
             width = 16,
             lspace = spacer,
             rspace = if 2 * spacer + 69 < width {
                 spacer + 1
             } else {
                 spacer
             });
}

/// Pretty prints measurements at current step to screen
pub fn measurements(tau: f64, diff: f64, observables: &grid::Observables) -> String {
    //TODO: This is going to be called every output. Maybe generate a lazy_static value?
    let width = get_term_size();
    let spacer = (width - 69) / 2;
    if tau > 0.0 {
        format!("{:^space$}│{:>11.3} │{:>19.10e} │{:15.5} │{:15.5e} │",
                "",
                tau,
                observables.energy / observables.norm2,
                (observables.r2 / observables.norm2).sqrt(),
                diff,
                space = spacer)
    } else {
        format!("{:^space$}│{:>11.3} │{:>19.10e} │{:15.5} │{:>15} │",
                "",
                tau,
                observables.energy / observables.norm2,
                (observables.r2 / observables.norm2).sqrt(),
                "--   ",
                space = spacer)

    }
}

/// Pretty print final summary
pub fn summary(observables: &grid::Observables, wnum: u8, numx: f64) {
    let width = get_term_size();
    let spacer = (width - 69) / 2;
    let energy = observables.energy / observables.norm2;
    let binding = observables.energy - observables.v_infinity / observables.norm2;
    let r_norm = (observables.r2 / observables.norm2).sqrt();
    println!("{:═^lspace$}╧{:═^twidth$}╧{:═^ewidth$}╧{:═^width$}╧{:═^width$}╧{:═^rspace$}",
             "",
             "",
             "",
             "",
             "",
             "",
             twidth = 12,
             ewidth = 20,
             width = 16,
             lspace = spacer,
             rspace = if 2 * spacer + 69 < width {
                 spacer + 1
             } else {
                 spacer
             });
    if let 0 = wnum {
        println!("══▶ Ground state energy = {}", energy);
        println!("══▶ Ground state binding energy = {}", binding);
    } else {
        let state = Ordinal::from(wnum);
        println!("══▶ {} excited state energy = {}", state, energy);
        println!("══▶ {} excited state binding energy = {}",
                 state,
                 binding);
    }
    println!("══▶ rᵣₘₛ = {}", r_norm);
    println!("══▶ L/rᵣₘₛ = {}", numx / r_norm);
    println!("");
}

/// Generates a unique folder inside an `output` directory for the current simulation.
///
/// # Panics
/// * If directory can not be created. Gives `std::io::Error`.
pub fn check_output_dir(project: &str) {
    let proj_dir = create_dir_all(get_project_dir(project));
    match proj_dir {
        Ok(_) => {}
        Err(err) => panic!("Cannot create project directory: {}", err),
    }
}

/// Each simulation has a unique folder output so as not to overwrite other instances.
/// This function gets the name of the current folder.
///
/// # Arguments
///
/// * `project` - The name of the currently active project as set in the configuration file
///
/// # Retuns
///
/// A string containting the location of the output folder, comprised of a sanitized
/// project name, followed by the start date/time of the simulation.
pub fn get_project_dir(project: &str) -> String {
    format!("./output/{}_{}", sanitize_string(project), &**PROJDATE)
}

/// Copies the current configuration file to the project folder
pub fn copy_config(project: &str) {
    let result = copy("./wafer.cfg", get_project_dir(project) + "/wafer.cfg");
    match result {
        Ok(_) => {}
        Err(err) => {
            panic!("Error copying configuration file to project directory: {}",
                   err)
        }
    }
}

/// Uses `term_size` to pull in the terminal width and from there sets the output
/// pretty printing value to an appropriate value (between 70-100).
pub fn get_term_size() -> usize {
    let mut term_width = 100;
    if let Some((width, _)) = term_size::dimensions() {
        if width <= 70 {
            term_width = 70;
        } else if width < term_width {
            term_width = width;
        }
    }
    term_width
}

/// Sanitizes strings such that they will create safe filenames.
/// For now, only used with the `project_name` variable in the configuration.
fn sanitize_string(component: &str) -> String {
    let mut buffer = String::with_capacity(component.len());
    for (i, c) in component.chars().enumerate() {
        let is_lower = 'a' <= c && c <= 'z';
        let is_upper = 'A' <= c && c <= 'Z';
        let is_letter = is_upper || is_lower;
        let is_number = '0' <= c && c <= '9';
        let is_space = c == ' ';
        let is_hyphen = c == '-';
        let is_underscore = c == '_';
        let is_period = c == '.' && i != 0; // Disallow accidentally hidden folders
        let is_valid = is_letter || is_number || is_hyphen || is_underscore || is_period;
        if is_valid {
            buffer.push(c);
        }
        if is_space {
            buffer.push('_'); //Convert spaces to underscores.
        } else {
            buffer.push_str(&format!(",{},", c as u32));
        }
    }
    buffer
}
<commit_msg>Missread clippy info and mangled folder output. This fixes the issue<commit_after>use chrono::Local;
use ndarray::Array3;
use ordinal::Ordinal;
use rayon;
use std::fs::{copy, create_dir_all, File};
use std::io::Error;
use std::io::prelude::*;
use term_size;
use ansi_term::Colour::Blue;

use grid;

lazy_static! {
    /// Date & time at which the simulation was started. Used as a unique identifier for
    /// the output directory of a run.
    static ref PROJDATE: String = Local::now().format("%Y-%m-%d_%H:%M:%S").to_string();
}

/// Simply prints the Wafer banner with current commit info and thread count.
pub fn print_banner(sha: &str) {
    println!("                    {}", Blue.paint("___"));
    println!("   __      ____ _  {}__ _ __", Blue.paint("/ __\\"));
    println!("   \\ \\ /\\ / / _` |{} / _ \\ '__|", Blue.paint("/ /"));
    println!("    \\ V  V / (_| {}|  __/ |    Current build SHA1: {}",
             Blue.paint("/ _\\"),
             sha);
    println!("     \\_/\\_/ \\__,{}   \\___|_|    Parallel tasks running on {} threads.",
             Blue.paint("/ /"),
             rayon::current_num_threads());
    println!("              {}", Blue.paint("\\__/"));
    println!("");
}

/// Outputs the current potential to disk in a plain, csv format
///
/// # Arguments
/// *`v` - The potential to output
///
/// # Returns
/// * A result type with a `std::io::Error`. The result value is a true bool
/// as we really only want to error check the result.
pub fn potential_plain(v: &Array3<f64>, project: &str) -> Result<bool, Error> {
    let mut buffer = File::create(get_project_dir(project) + "/potential.csv")?;
    let dims = v.dim();
    let work = v.slice(s![3..(dims.0 as isize) - 3,
                          3..(dims.1 as isize) - 3,
                          3..(dims.2 as isize) - 3]);
    for ((i, j, k), el) in work.indexed_iter() {
        let output = format!("{}, {}, {}, {:e}\n", i, j, k, el);
        buffer.write_all(output.as_bytes())?;
    }
    Ok(true)
}

/// Outputs a wavefunction to disk in a plain, csv format
///
/// # Arguments
/// * `phi` - The wavefunction to output
/// * `num` - The wavefunction's excited state value for file naming.
/// * `converged` - a bool advising the state of the wavefunction. If false, the filename
/// will have `_partial` appended to it to indicate a restart is required.
///
/// # Returns
/// * A result type with a `std::io::Error`. The result value is a true bool
/// as we really only want to error check the result.
pub fn wavefunction_plain(phi: &Array3<f64>,
                          num: u8,
                          converged: bool,
                          project: &str)
                          -> Result<bool, Error> {
    let filename = format!("{}/wavefunction_{}{}.csv",
                           get_project_dir(project),
                           num,
                           if converged { "" } else { "_partial" });
    let mut buffer = File::create(filename)?;
    let dims = phi.dim();
    let work = phi.slice(s![3..(dims.0 as isize) - 3,
                            3..(dims.1 as isize) - 3,
                            3..(dims.2 as isize) - 3]);
    for ((i, j, k), el) in work.indexed_iter() {
        let output = format!("{}, {}, {}, {:e}\n", i, j, k, el);
        buffer.write_all(output.as_bytes())?;
    }
    Ok(true)
}

/// Pretty prints a header for the subsequent observable data
pub fn print_observable_header(wnum: u8) {
    let width = get_term_size();
    let spacer = (width - 69) / 2;
    let col2 = 37; //Energy+rrms+1
    println!("");
    if let 0 = wnum {
        println!("{:═^lspace$}╤{:═^twidth$}╤{:═^w$}╤{:═^width$}╤{:═^rspace$}",
                 "",
                 "",
                 " Ground state caclulation ",
                 "",
                 "",
                 twidth = 12,
                 width = 16,
                 w = col2,
                 lspace = spacer,
                 rspace = if 2 * spacer + 69 < width {
                     spacer + 1
                 } else {
                     spacer
                 });
    } else {
        println!("{:═^lspace$}╤{:═^twidth$}╤{:═^w$}╤{:═^width$}╤{:═^rspace$}",
                 "",
                 "",
                 format!(" {} excited state caclulation ", Ordinal::from(wnum)),
                 "",
                 "",
                 twidth = 12,
                 width = 16,
                 w = col2,
                 lspace = spacer,
                 rspace = if 2 * spacer + 69 < width {
                     spacer + 1
                 } else {
                     spacer
                 });
    }
    println!("{:^space$}│{:^twidth$}│{:^ewidth$}│{:^width$}│{:^width$}│",
             "",
             "Time (τ)",
             "Energy",
             "rᵣₘₛ",
             "Difference",
             twidth = 12,
             ewidth = 20,
             width = 16,
             space = spacer);
    println!("{:─^lspace$}┼{:─^twidth$}┼{:─^ewidth$}┼{:─^width$}┼{:─^width$}┼{:─^rspace$}",
             "",
             "",
             "",
             "",
             "",
             "",
             twidth = 12,
             ewidth = 20,
             width = 16,
             lspace = spacer,
             rspace = if 2 * spacer + 69 < width {
                 spacer + 1
             } else {
                 spacer
             });
}

/// Pretty prints measurements at current step to screen
pub fn measurements(tau: f64, diff: f64, observables: &grid::Observables) -> String {
    //TODO: This is going to be called every output. Maybe generate a lazy_static value?
    let width = get_term_size();
    let spacer = (width - 69) / 2;
    if tau > 0.0 {
        format!("{:^space$}│{:>11.3} │{:>19.10e} │{:15.5} │{:15.5e} │",
                "",
                tau,
                observables.energy / observables.norm2,
                (observables.r2 / observables.norm2).sqrt(),
                diff,
                space = spacer)
    } else {
        format!("{:^space$}│{:>11.3} │{:>19.10e} │{:15.5} │{:>15} │",
                "",
                tau,
                observables.energy / observables.norm2,
                (observables.r2 / observables.norm2).sqrt(),
                "--   ",
                space = spacer)

    }
}

/// Pretty print final summary
pub fn summary(observables: &grid::Observables, wnum: u8, numx: f64) {
    let width = get_term_size();
    let spacer = (width - 69) / 2;
    let energy = observables.energy / observables.norm2;
    let binding = observables.energy - observables.v_infinity / observables.norm2;
    let r_norm = (observables.r2 / observables.norm2).sqrt();
    println!("{:═^lspace$}╧{:═^twidth$}╧{:═^ewidth$}╧{:═^width$}╧{:═^width$}╧{:═^rspace$}",
             "",
             "",
             "",
             "",
             "",
             "",
             twidth = 12,
             ewidth = 20,
             width = 16,
             lspace = spacer,
             rspace = if 2 * spacer + 69 < width {
                 spacer + 1
             } else {
                 spacer
             });
    if let 0 = wnum {
        println!("══▶ Ground state energy = {}", energy);
        println!("══▶ Ground state binding energy = {}", binding);
    } else {
        let state = Ordinal::from(wnum);
        println!("══▶ {} excited state energy = {}", state, energy);
        println!("══▶ {} excited state binding energy = {}",
                 state,
                 binding);
    }
    println!("══▶ rᵣₘₛ = {}", r_norm);
    println!("══▶ L/rᵣₘₛ = {}", numx / r_norm);
    println!("");
}

/// Generates a unique folder inside an `output` directory for the current simulation.
///
/// # Panics
/// * If directory can not be created. Gives `std::io::Error`.
pub fn check_output_dir(project: &str) {
    let proj_dir = create_dir_all(get_project_dir(project));
    match proj_dir {
        Ok(_) => {}
        Err(err) => panic!("Cannot create project directory: {}", err),
    }
}

/// Each simulation has a unique folder output so as not to overwrite other instances.
/// This function gets the name of the current folder.
///
/// # Arguments
///
/// * `project` - The name of the currently active project as set in the configuration file
///
/// # Retuns
///
/// A string containting the location of the output folder, comprised of a sanitized
/// project name, followed by the start date/time of the simulation.
pub fn get_project_dir(project: &str) -> String {
    format!("./output/{}_{}", sanitize_string(project), &**PROJDATE)
}

/// Copies the current configuration file to the project folder
pub fn copy_config(project: &str) {
    let result = copy("./wafer.cfg", get_project_dir(project) + "/wafer.cfg");
    match result {
        Ok(_) => {}
        Err(err) => {
            panic!("Error copying configuration file to project directory: {}",
                   err)
        }
    }
}

/// Uses `term_size` to pull in the terminal width and from there sets the output
/// pretty printing value to an appropriate value (between 70-100).
pub fn get_term_size() -> usize {
    let mut term_width = 100;
    if let Some((width, _)) = term_size::dimensions() {
        if width <= 70 {
            term_width = 70;
        } else if width < term_width {
            term_width = width;
        }
    }
    term_width
}

/// Sanitizes strings such that they will create safe filenames.
/// For now, only used with the `project_name` variable in the configuration.
fn sanitize_string(component: &str) -> String {
    let mut buffer = String::with_capacity(component.len());
    for (i, c) in component.chars().enumerate() {
        let is_lower = 'a' <= c && c <= 'z';
        let is_upper = 'A' <= c && c <= 'Z';
        let is_letter = is_upper || is_lower;
        let is_number = '0' <= c && c <= '9';
        let is_space = c == ' ';
        let is_hyphen = c == '-';
        let is_underscore = c == '_';
        let is_period = c == '.' && i != 0; // Disallow accidentally hidden folders
        let is_valid = is_letter || is_number || is_hyphen || is_underscore || is_period;
        if is_valid {
            buffer.push(c);
        } else if is_space {
            buffer.push('_'); //Convert spaces to underscores.
        } else {
            buffer.push_str(&format!(",{},", c as u32));
        }
    }
    buffer
}
<|endoftext|>


<commit_before>
use postgres::{
    Rows,
    Connection,
    Statement
};

use postgres::Result as PostgresResult;
use postgres::types::ToSql;
use deuterium::{SqlContext, AsPostgresValue, QueryToSql};

pub type PostgresPool = ::r2d2::Pool<
    Connection,
    ::r2d2_postgres::Error,
    ::r2d2_postgres::PostgresPoolManager,
    ::r2d2::NoopErrorHandler>;

pub struct PostgresAdapter;

impl PostgresAdapter {
    pub fn prepare_query<'conn>(query: &QueryToSql, cn: &'conn Connection) -> (SqlContext, PostgresResult<Statement<'conn>>){
        let mut ctx = SqlContext::new(box ::deuterium::sql::adapter::PostgreSqlAdapter);
        let sql = query.to_final_sql(&mut ctx);

        (ctx, cn.prepare(sql.as_slice()))
    }

    pub fn prepare_params<'a>(
            ext_params: &[&'a ToSql],
            ctx_params: &'a[Box<AsPostgresValue + Send + Sync>]
        ) -> Vec<&'a ToSql + 'a> {

        let mut final_params = vec![];

        for param in ext_params.iter() {
            final_params.push(*param);
        }

        for param in ctx_params.iter() {
            final_params.push(param.as_postgres_value());
        }

        final_params
    }

    pub fn exec<'conn, 'a>(stm: &'conn Statement<'conn>, params: &[&'a ToSql], ctx_params: &'a[Box<AsPostgresValue + Send + Sync>]) -> PostgresResult<Rows<'conn>> {
        stm.query(PostgresAdapter::prepare_params(params, ctx_params).as_slice())
    }
}<commit_msg>feat: add more routine stuff to pg adapter<commit_after>
use postgres::{
    Rows,
    Connection,
    Statement
};

use postgres::Result as PostgresResult;
use postgres::types::ToSql;
use deuterium::{SqlContext, AsPostgresValue, QueryToSql};

pub type PostgresPool = ::r2d2::Pool<
    Connection,
    ::r2d2_postgres::Error,
    ::r2d2_postgres::PostgresPoolManager,
    ::r2d2::NoopErrorHandler>;

pub type PostgresPooledConnection<'a> = ::r2d2::PooledConnection<
    'a,
    ::postgres::Connection,
    ::r2d2_postgres::Error,
    ::r2d2_postgres::PostgresPoolManager,
    ::r2d2::NoopErrorHandler
>;

pub fn setup(cn_str: &str, pool_size: uint) -> PostgresPool {
    let manager = ::r2d2_postgres::PostgresPoolManager::new(cn_str, ::postgres::NoSsl);
    let config = ::r2d2::Config {
        pool_size: pool_size,
        test_on_check_out: true,
        ..::std::default::Default::default()
    };

    let handler = ::r2d2::NoopErrorHandler;
    ::r2d2::Pool::new(config, manager, handler).unwrap()
}

pub struct PostgresAdapter;

impl PostgresAdapter {
    pub fn prepare_query<'conn>(query: &QueryToSql, cn: &'conn Connection) -> (SqlContext, PostgresResult<Statement<'conn>>){
        let mut ctx = SqlContext::new(box ::deuterium::sql::adapter::PostgreSqlAdapter);
        let sql = query.to_final_sql(&mut ctx);

        (ctx, cn.prepare(sql.as_slice()))
    }

    pub fn prepare_params<'a>(
            ext_params: &[&'a ToSql],
            ctx_params: &'a[Box<AsPostgresValue + Send + Sync>]
        ) -> Vec<&'a ToSql + 'a> {

        let mut final_params = vec![];

        for param in ext_params.iter() {
            final_params.push(*param);
        }

        for param in ctx_params.iter() {
            final_params.push(param.as_postgres_value());
        }

        final_params
    }

    pub fn exec<'conn, 'a>(stm: &'conn Statement<'conn>, params: &[&'a ToSql], ctx_params: &'a[Box<AsPostgresValue + Send + Sync>]) -> PostgresResult<Rows<'conn>> {
        stm.query(PostgresAdapter::prepare_params(params, ctx_params).as_slice())
    }
}<|endoftext|>


<commit_before>use nom::*;
use std::str;

// http://rust.unhandledexpression.com/nom/macro.escaped!.html
// http://rust.unhandledexpression.com/nom/
// https://fr.wikipedia.org/wiki/Comma-separated_values
// https://github.com/Geal/nom/wiki/Making-a-new-parser-from-scratch
// https://github.com/Geal/nom
// http://rust.unhandledexpression.com/nom/macro.escaped!.html
named!(string_between_quotes, delimited!(char!('\"'), is_not!("\""), char!('\"')));
named!(get_cell, take_while!(is_not_cell_end));
named!(get_line, take_until!("\n"));
named!(consume_useless_chars, take_while!(is_whitespace));

fn is_whitespace(c: u8) -> bool {
    c as char == ' ' || c as char == '\t'
}

fn is_not_cell_end(c: u8) -> bool {
    c as char != ',' && c as char != '\n'
}

fn get_column_value<'a>(entry: &'a [u8]) -> IResult<&'a [u8], &'a [u8]> {
    match consume_useless_chars(entry) {
        IResult::Done(out, _) => {
            if out.len() < 1 {
                IResult::Done(b"", b"")
            } else if out[0] as char == '\"' {
                match string_between_quotes(out) {
                    IResult::Done(i, out) => {
                        match consume_useless_chars(i) {
                            IResult::Done(i, _) => {
                                if is_not_cell_end(i[0]) {
                                    panic!("Expected `,`, found `{}`", i[0] as char)
                                } else {
                                    IResult::Done(i, out)
                                }
                            }
                            x => x,
                        }
                    }
                    x => x,
                }
            } else if out[0] as char == '\n' {
                IResult::Done(b"", b"")
            } else {
                get_cell(out)
            }
        },
        x => x,
    }
}

fn get_line_values<'a>(ret: &mut Vec<String>, entry: &'a [u8]) -> IResult<&'a [u8], &'a [u8]> {
    match get_column_value(entry) {
        IResult::Done(in_, out) => {
            if out.len() < 1 {
                IResult::Done(b"", b"")
            } else {
                if let Ok(s) = str::from_utf8(out) {
                    ret.push(s.to_owned());
                }
                if in_.len() > 0 && in_[0] as char != '\n' {
                    match take!(in_, 1) {
                        IResult::Done(in_, _) => get_line_values(ret, in_),
                        x => x,
                    }
                } else {
                    IResult::Done(b"", b"")
                }
            }
        }
        ref n if n.is_incomplete() => {
            if let Some(out) = n.remaining_input() {
                if out.len() < 1 {
                    IResult::Done(b"", b"")
                } else {
                    if let Ok(s) = str::from_utf8(out) {
                        ret.push(s.to_owned());
                    }
                    IResult::Done(b"", b"")
                }
            } else {
                IResult::Done(b"", b"")
            }
        }
        x => x,
    }
}

fn get_lines_values(ret: &mut Vec<Vec<String>>, entry: &[u8]) {
    match get_line(entry) {
        IResult::Done(in_, out) => {
            let mut line = vec!();

            get_line_values(&mut line, out);
            if line.len() < 1 {
                return;
            }
            ret.push(line);
            if in_.len() > 0 && in_[0] as char == '\n' {
                match take!(in_, 1) {
                    IResult::Done(in_, _) => get_lines_values(ret, in_),
                    _ => {},
                }
                get_lines_values(ret, in_)
            }
        }
        _ => {}
    }
}

#[test]
fn check_string_between_quotes() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";

    match string_between_quotes(f) {
        IResult::Done(in_, out) => {
            assert_eq!(out, b"nom");
            assert_eq!(in_, b",age\ncarles,30\nlaure,28\n");
        },
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_cell() {
    let f = b"age\ncarles,30\n";
    let g = b"age2,carles,30\n";

    match get_cell(f) {
        IResult::Done(_, out) => assert_eq!(out, b"age"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
    match get_cell(g) {
        IResult::Done(_, out) => assert_eq!(out, b"age2"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_line() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";

    match get_line(f) {
        IResult::Done(_, out) => assert_eq!(out, b"\"nom\",age"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_line_values() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";
    let mut cells = vec!();

    get_line_values(&mut cells, f);
    assert_eq!(cells, vec!("nom".to_owned(), "age".to_owned()));
}

#[test]
fn check_get_lines_values() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";
    let mut cells = vec!();

    get_lines_values(&mut cells, f);
    assert_eq!(cells, vec!(
                           vec!("nom".to_owned(), "age".to_owned()),
                           vec!("carles".to_owned(), "30".to_owned()),
                           vec!("laure".to_owned(), "28".to_owned())));
}
<commit_msg>Still working on it<commit_after>use nom::*;
use std::str;

// http://rust.unhandledexpression.com/nom/macro.escaped!.html
// http://rust.unhandledexpression.com/nom/
// https://fr.wikipedia.org/wiki/Comma-separated_values
// https://github.com/Geal/nom/wiki/Making-a-new-parser-from-scratch
// https://github.com/Geal/nom
// http://rust.unhandledexpression.com/nom/macro.escaped!.html
named!(string_between_quotes, delimited!(char!('\"'), is_not!("\""), char!('\"')));
named!(get_cell, take_while!(is_not_cell_end));
named!(get_line, take_until!("\n"));
named!(consume_useless_chars, take_while!(is_whitespace));

fn is_whitespace(c: u8) -> bool {
    c as char == ' ' || c as char == '\t'
}

fn is_not_cell_end(c: u8) -> bool {
    c as char != ',' && c as char != '\n'
}

fn get_column_value<'a>(entry: &'a [u8]) -> IResult<&'a [u8], &'a [u8]> {
    match consume_useless_chars(entry) {
        IResult::Done(out, _) => {
            if out.len() < 1 {
                IResult::Done(b"", b"")
            } else if out[0] as char == '\"' {
                match string_between_quotes(out) {
                    IResult::Done(i, out) => {
                        match consume_useless_chars(i) {
                            IResult::Done(i, _) => {
                                if is_not_cell_end(i[0]) {
                                    panic!("Expected `,`, found `{}`", i[0] as char)
                                } else {
                                    IResult::Done(i, out)
                                }
                            }
                            x => x,
                        }
                    }
                    x => x,
                }
            } else if out[0] as char == '\n' {
                IResult::Done(b"", b"")
            } else {
                get_cell(out)
            }
        },
        x => x,
    }
}

fn get_line_values<'a>(ret: &mut Vec<String>, entry: &'a [u8]) -> IResult<&'a [u8], &'a [u8]> {
    match get_column_value(entry) {
        IResult::Done(in_, out) => {
            if in_.len() < 1 && out.len() < 1 { // this condition fails
                ret.push(String::new());
                IResult::Done(b"", b"")
            } else {
                if let Ok(s) = str::from_utf8(out) {
                    ret.push(s.to_owned());
                }
                if in_.len() > 0 && in_[0] as char != '\n' {
                    match take!(in_, 1) {
                        IResult::Done(in_, _) => get_line_values(ret, in_),
                        x => x,
                    }
                } else {
                    IResult::Done(b"", b"")
                }
            }
        }
        ref n if n.is_incomplete() => {
            if let Some(out) = n.remaining_input() {
                if out.len() < 1 {
                    IResult::Done(b"", b"")
                } else {
                    if let Ok(s) = str::from_utf8(out) {
                        ret.push(s.to_owned());
                    }
                    IResult::Done(b"", b"")
                }
            } else {
                IResult::Done(b"", b"")
            }
        }
        x => x,
    }
}

fn get_lines_values(ret: &mut Vec<Vec<String>>, entry: &[u8]) {
    match get_line(entry) {
        IResult::Done(in_, out) => {
            let mut line = vec!();

            get_line_values(&mut line, out);
            if line.len() < 1 {
                return;
            }
            ret.push(line);
            if in_.len() > 0 && in_[0] as char == '\n' {
                match take!(in_, 1) {
                    IResult::Done(in_, _) => get_lines_values(ret, in_),
                    _ => {},
                }
                get_lines_values(ret, in_)
            }
        }
        _ => {}
    }
}

#[test]
fn check_string_between_quotes() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";

    match string_between_quotes(f) {
        IResult::Done(in_, out) => {
            assert_eq!(out, b"nom");
            assert_eq!(in_, b",age\ncarles,30\nlaure,28\n");
        },
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_cell() {
    let f = b"age\ncarles,30\n";
    let g = b"age2,carles,30\n";

    match get_cell(f) {
        IResult::Done(_, out) => assert_eq!(out, b"age"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
    match get_cell(g) {
        IResult::Done(_, out) => assert_eq!(out, b"age2"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_line() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";

    match get_line(f) {
        IResult::Done(_, out) => assert_eq!(out, b"\"nom\",age"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_line_values() {
    let f = b"\"nom\",,age\ncarles,30\nlaure,28\n";
    let g = b"\"nom\",age,\ncarles,30\nlaure,28\n";
    let mut cells = vec!();

    get_line_values(&mut cells, f);
    assert_eq!(cells, vec!("nom".to_owned(), "".to_owned(), "age".to_owned()));
    let mut cells = vec!();
    get_line_values(&mut cells, g);
    assert_eq!(cells, vec!("nom".to_owned(), "age".to_owned(), "".to_owned()));
}

#[test]
fn check_get_lines_values() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";
    let mut cells = vec!();

    get_lines_values(&mut cells, f);
    assert_eq!(cells, vec!(
                           vec!("nom".to_owned(), "age".to_owned()),
                           vec!("carles".to_owned(), "30".to_owned()),
                           vec!("laure".to_owned(), "28".to_owned())));
}
/*
use nom::*;
use std::str;
use std::io::prelude::*;
use std::fs::File;

// http://rust.unhandledexpression.com/nom/macro.escaped!.html
// http://rust.unhandledexpression.com/nom/
// https://fr.wikipedia.org/wiki/Comma-separated_values
// https://github.com/Geal/nom/wiki/Making-a-new-parser-from-scratch
// https://github.com/Geal/nom
// http://rust.unhandledexpression.com/nom/macro.escaped!.html
named!(string_between_quotes, delimited!(char!('\"'), is_not!("\""), char!('\"')));
named!(get_cell, take_while!(is_not_cell_end));
named!(get_line, take_until!("\n"));
named!(consume_useless_chars, take_while!(is_whitespace));

fn is_whitespace(c: u8) -> bool {
    c as char == ' ' || c as char == '\t'
}

fn is_not_cell_end(c: u8) -> bool {
    c as char != ',' && c as char != '\n'
}

fn get_column_value<'a>(entry: &'a [u8]) -> IResult<&'a [u8], &'a [u8]> {
    match consume_useless_chars(entry) {
        IResult::Done(out, _) => {
            if out.len() < 1 {
                IResult::Done(b"", b"")
            } else if out[0] as char == '\"' {
                match string_between_quotes(out) {
                    IResult::Done(i, out) => {
                        match consume_useless_chars(i) {
                            IResult::Done(i, _) => {
                                if is_not_cell_end(i[0]) {
                                    panic!("Expected `,`, found `{}`", i[0] as char)
                                } else {
                                    IResult::Done(i, out)
                                }
                            }
                            x => x,
                        }
                    }
                    x => x,
                }
            } else if out[0] as char == '\n' {
                IResult::Done(b"", b"")
            } else {
                get_cell(out)
            }
        },
        x => x,
    }
}

fn get_line_values<'a>(ret: &mut Vec<String>, entry: &'a [u8]) -> IResult<&'a [u8], &'a [u8]> {
    match get_column_value(entry) {
        IResult::Done(in_, out) => {
            if in_.len() < 1 {
                IResult::Done(b"", b"")
            } else {
                if let Ok(s) = str::from_utf8(out) {
                    ret.push(s.to_owned());
                }
                if in_.len() > 0 && in_[0] as char != '\n' {
                    match take!(in_, 1) {
                        IResult::Done(in_, _) => get_line_values(ret, in_),
                        x => x,
                    }
                } else {
                    IResult::Done(b"", b"")
                }
            }
        }
        ref n if n.is_incomplete() => {
            if let Some(out) = n.remaining_input() {
                if out.len() < 1 {
                    IResult::Done(b"", b"")
                } else {
                    if let Ok(s) = str::from_utf8(out) {
                        ret.push(s.to_owned());
                    }
                    IResult::Done(b"", b"")
                }
            } else {
                IResult::Done(b"", b"")
            }
        }
        x => x,
    }
}

fn get_lines_values(ret: &mut Vec<Vec<String>>, entry: &[u8]) {
    match get_line(entry) {
        IResult::Done(in_, out) => {
            let mut line = vec!();

            get_line_values(&mut line, out);
            if line.len() < 1 {
                return;
            }
            if ret.len() > 0 && ret[0].len() != line.len() {
                panic!("Line {} doesn't have the same length ({} instead of {})",
                    ret.len(), line.len(), ret[0].len())
            }
            ret.push(line);
            if in_.len() > 0 && in_[0] as char == '\n' {
                match take!(in_, 1) {
                    IResult::Done(in_, _) => get_lines_values(ret, in_),
                    _ => {},
                }
            }
        }
        _ => {}
    }
}

pub fn parse_csv_from_slice(entry: &[u8]) -> Vec<Vec<String>> {
    let mut ret = vec!();

    get_lines_values(&mut ret, entry);
    ret
}

pub fn parse_csv_from_file(filename: &str) -> Vec<Vec<String>> {
    let mut f = File::open(filename).unwrap();
    let mut buffer = vec!();

    f.read_to_end(&mut buffer).unwrap();
    parse_csv_from_slice(&buffer)
}

pub fn parse_csv(entry: &str) -> Vec<Vec<String>> {
    parse_csv_from_slice(entry.as_bytes())
}

#[test]
fn check_string_between_quotes() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";

    match string_between_quotes(f) {
        IResult::Done(in_, out) => {
            assert_eq!(out, b"nom");
            assert_eq!(in_, b",age\ncarles,30\nlaure,28\n");
        },
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_cell() {
    let f = b"age\ncarles,30\n";
    let g = b"age2,carles,30\n";

    match get_cell(f) {
        IResult::Done(_, out) => assert_eq!(out, b"age"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
    match get_cell(g) {
        IResult::Done(_, out) => assert_eq!(out, b"age2"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_line() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";

    match get_line(f) {
        IResult::Done(_, out) => assert_eq!(out, b"\"nom\",age"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_line_values() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";
    let mut cells = vec!();

    get_line_values(&mut cells, f);
    assert_eq!(cells, vec!("nom".to_owned(), "age".to_owned()));
}

#[test]
fn check_get_lines_values() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";
    let mut cells = vec!();

    get_lines_values(&mut cells, f);
    assert_eq!(cells, vec!(
                           vec!("nom".to_owned(), "age".to_owned()),
                           vec!("carles".to_owned(), "30".to_owned()),
                           vec!("laure".to_owned(), "28".to_owned())));
}
*/<|endoftext|>


<commit_before>//! A parser for lambda expressions with
//! [De Bruijn indices](https://en.wikipedia.org/wiki/De_Bruijn_index)

use term::*;
use term::Term::*;
use self::Token::*;
use self::Error::*;
use self::Expression::*;

/// A type to represent a parsing error.
#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidCharacter((usize, char)),
    InvalidExpression,
    EmptyExpression
}

#[derive(Debug, PartialEq)]
enum Token {
    Lambda,
    Lparen,
    Rparen,
    Number(usize)
}

fn tokenize(input: &str) -> Result<Vec<Token>, Error> {
    let mut chars = input.chars();
    let mut tokens = Vec::new();
    let mut position = 0;

    while let Some(c) = chars.next() {
        match c {
     '\\' | 'λ' => { tokens.push(Lambda) },
            '(' => { tokens.push(Lparen) },
            ')' => { tokens.push(Rparen) },
             x  => {
                if let Some(n) = x.to_digit(16) {
                    tokens.push(Number(n as usize))
                } else if x.is_whitespace() {
                    ()
                } else {
                    return Err(InvalidCharacter((position, x)))
                }
            }
        }
        position += if c == 'λ' { 2 } else { 1 };
    }

    Ok(tokens)
}

#[derive(Debug, PartialEq)]
enum Expression {
    Abstraction,
    Sequence(Vec<Expression>),
    Variable(usize)
}

fn _get_ast(tokens: &[Token], pos: &mut usize) -> Result<Expression, Error> {
    let mut expr = Vec::new();

    if tokens.is_empty() { return Err(EmptyExpression) }

    while *pos < tokens.len() {
        match tokens[*pos] {
            Lambda => {
                expr.push(Abstraction)
            },
            Number(i) => {
                expr.push(Variable(i))
            },
            Lparen => {
                *pos += 1;
                let subtree = try!(_get_ast(&tokens, pos));
                expr.push(subtree);
            },
            Rparen => {
                return Ok(Sequence(expr))
            }
        }
        *pos += 1;
    }

    Ok(Sequence(expr))
}

fn get_ast(tokens: &[Token]) -> Result<Expression, Error> {
    let mut pos = 0;

    _get_ast(tokens, &mut pos)
}

/// Parses the input `&str` as a lambda `Term`. The lambdas can be represented either with the
/// greek letter (λ) or a backslash (\\ - less aesthetic, but only one byte in size), the De Bruijn
/// indices start with 1 and are hexadecimal digits, and whitespaces are ignored.
///
/// # Example
/// ```
/// use lambda_calculus::parser::parse;
/// use lambda_calculus::arithmetic::{succ, pred};
///
/// assert_eq!(parse(&"λ λ λ 2 (3 2 1)"), Ok(succ()));
/// assert_eq!(parse(&r#"\ \ \ 2 (3 2 1)"#), Ok(succ()));
/// assert_eq!(parse(&"λλλ3(λλ1(24))(λ2)(λ1)"), Ok(pred()));
/// ```
pub fn parse(input: &str) -> Result<Term, Error> {
    let tokens = try!(tokenize(input));
    let ast = try!(get_ast(&tokens));

    let exprs = try!(if let Sequence(exprs) = ast { Ok(exprs) } else { Err(InvalidExpression) });

    let mut stack = Vec::new();
    let mut output = Vec::new();
    let term = fold_exprs(&exprs, &mut stack, &mut output);

    term
}

fn fold_exprs(exprs: &[Expression], stack: &mut Vec<Expression>, output: &mut Vec<Term>)
    -> Result<Term, Error>
{
    let mut iter = exprs.iter();

    while let Some(ref expr) = iter.next() {
        match **expr {
            Variable(i) => output.push(Var(i)),
            Abstraction => stack.push(Abstraction),
            Sequence(ref exprs) => {
                let mut stack2 = Vec::new();
                let mut output2 = Vec::new();
                let subexpr = try!(fold_exprs(&exprs, &mut stack2, &mut output2));
                output.push(subexpr)
            }
        }
    }

    let mut ret = try!(fold_terms(output.drain(..).collect()));

    while let Some(Abstraction) = stack.pop() {
        ret = abs(ret);
    }

    Ok(ret)
}

fn fold_terms(mut terms: Vec<Term>) -> Result<Term, Error> {
    if terms.len() > 1 {
        terms.reverse();
        let fst = terms.pop().unwrap();
        terms.reverse();
        Ok( terms.into_iter().fold(fst, |acc, t| app(acc, t)) )
    } else if terms.len() == 1 {
        Ok( terms.pop().unwrap() )
    } else {
        Err(EmptyExpression)
    }
}

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

    #[test]
    fn tokenization_error() {
        assert_eq!(tokenize(&"λλx2"), Err(InvalidCharacter((4, 'x'))))
    }

    #[test]
    fn tokenization_success() {
        let quine = "λ 1 ( (λ 1 1) (λ λ λ λ λ 1 4 (3 (5 5) 2) ) ) 1";
        let tokens = tokenize(&quine);

        assert!(tokens.is_ok());
        assert_eq!(tokens.unwrap(), vec![Lambda, Number(1), Lparen, Lparen, Lambda, Number(1),
            Number(1), Rparen, Lparen, Lambda, Lambda, Lambda, Lambda, Lambda, Number(1),
            Number(4), Lparen, Number(3), Lparen, Number(5), Number(5), Rparen, Number(2),
            Rparen, Rparen, Rparen, Number(1)]);
    }

    #[test]
    fn alternative_lambda_parsing() {
        assert_eq!(parse(&"\\\\\\2(321)"), parse(&"λλλ2(321)"))
    }

    #[test]
    fn succ_ast() {
        let tokens = tokenize(&"λλλ2(321)").unwrap();
        let ast = get_ast(&tokens);

        assert_eq!(ast,
            Ok(Sequence(vec![
                Abstraction,
                Abstraction,
                Abstraction,
                Variable(2),
                Sequence(vec![
                    Variable(3),
                    Variable(2),
                    Variable(1)
                ])
            ])
        ));
    }

    #[test]
    fn parse_y() {
        let y = "λ(λ2(11))(λ2(11))";
        assert_eq!(parse(&y).expect("parsing Y failed!"),
            abs(
                app(
                    abs(
                        app(
                            Var(2),
                            app(Var(1), Var(1))
                        )
                    ),
                    abs(
                        app(
                            Var(2),
                            app(Var(1), Var(1))
                        )
                    )
                )
            )
        );
    }

    #[test]
    fn parse_quine() {
        let quine = "λ1((λ11)(λλλλλ14(3(55)2)))1";
        assert_eq!(parse(&quine).expect("parsing QUINE failed!"),
            abs(app(app(Var(1), app(abs(app(Var(1), Var(1))), abs(abs(abs(abs(abs(app(app(Var(1),
            Var(4)), app(app(Var(3), app(Var(5), Var(5))), Var(2)))))))))), Var(1)))
        );
    }

    #[test]
    fn parse_blc() {
        let blc = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))\
                   (λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        assert_eq!(parse(&blc).expect("parsing BLC failed!"),
            app(app(abs(app(Var(1), Var(1))), abs(abs(abs(app(app(app(Var(1),
            abs(abs(abs(abs(app(Var(3), abs(app(app(Var(5), app(Var(3), abs(app(app(Var(2),
            app(Var(3), abs(abs(app(Var(3), abs(app(app(Var(1), Var(2)), Var(3)))))))), app(Var(4),
            abs(app(Var(4), abs(app(app(Var(3), Var(1)), app(Var(2), Var(1))))))))))),
            app(app(Var(1), app(Var(2), abs(app(Var(1), Var(2))))), abs(app(app(Var(4),
            abs(app(Var(4), abs(app(Var(2), app(Var(1), Var(4))))))), Var(5)))))))))))),
            app(Var(3), Var(3))), Var(2)))))), abs(app(Var(1), app(abs(app(Var(1), Var(1))),
            abs(app(Var(1), Var(1)))))))
        );
    }
}
<commit_msg>optimize parser a bit<commit_after>//! A parser for lambda expressions with
//! [De Bruijn indices](https://en.wikipedia.org/wiki/De_Bruijn_index)

use term::*;
use term::Term::*;
use self::Token::*;
use self::Error::*;
use self::Expression::*;

/// A type to represent a parsing error.
#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidCharacter((usize, char)),
    InvalidExpression,
    EmptyExpression
}

#[derive(Debug, PartialEq)]
enum Token {
    Lambda,
    Lparen,
    Rparen,
    Number(usize)
}

fn tokenize(input: &str) -> Result<Vec<Token>, Error> {
    let mut chars = input.chars();
    let mut tokens = Vec::new();
    let mut position = 0;

    while let Some(c) = chars.next() {
        match c {
     '\\' | 'λ' => { tokens.push(Lambda) },
            '(' => { tokens.push(Lparen) },
            ')' => { tokens.push(Rparen) },
             x  => {
                if let Some(n) = x.to_digit(16) {
                    tokens.push(Number(n as usize))
                } else if x.is_whitespace() {
                    ()
                } else {
                    return Err(InvalidCharacter((position, x)))
                }
            }
        }
        position += if c == 'λ' { 2 } else { 1 };
    }

    Ok(tokens)
}

#[derive(Debug, PartialEq)]
enum Expression {
    Abstraction,
    Sequence(Vec<Expression>),
    Variable(usize)
}

fn _get_ast(tokens: &[Token], pos: &mut usize) -> Result<Expression, Error> {
    let mut expr = Vec::new();

    if tokens.is_empty() { return Err(EmptyExpression) }

    while *pos < tokens.len() {
        match tokens[*pos] {
            Lambda => {
                expr.push(Abstraction)
            },
            Number(i) => {
                expr.push(Variable(i))
            },
            Lparen => {
                *pos += 1;
                let subtree = try!(_get_ast(&tokens, pos));
                expr.push(subtree);
            },
            Rparen => {
                return Ok(Sequence(expr))
            }
        }
        *pos += 1;
    }

    Ok(Sequence(expr))
}

fn get_ast(tokens: &[Token]) -> Result<Expression, Error> {
    let mut pos = 0;

    _get_ast(tokens, &mut pos)
}

/// Parses the input `&str` as a lambda `Term`. The lambdas can be represented either with the
/// greek letter (λ) or a backslash (\\ - less aesthetic, but only one byte in size), the De Bruijn
/// indices start with 1 and are hexadecimal digits, and whitespaces are ignored.
///
/// # Example
/// ```
/// use lambda_calculus::parser::parse;
/// use lambda_calculus::arithmetic::{succ, pred};
///
/// assert_eq!(parse(&"λ λ λ 2 (3 2 1)"), Ok(succ()));
/// assert_eq!(parse(&r#"\ \ \ 2 (3 2 1)"#), Ok(succ()));
/// assert_eq!(parse(&"λλλ3(λλ1(24))(λ2)(λ1)"), Ok(pred()));
/// ```
pub fn parse(input: &str) -> Result<Term, Error> {
    let tokens = try!(tokenize(input));
    let ast = try!(get_ast(&tokens));

    let exprs = try!(if let Sequence(exprs) = ast { Ok(exprs) } else { Err(InvalidExpression) });

    let mut stack = Vec::new();
    let mut output = Vec::new();
    let term = fold_exprs(&exprs, &mut stack, &mut output);

    term
}

fn fold_exprs(exprs: &[Expression], stack: &mut Vec<Expression>, output: &mut Vec<Term>)
    -> Result<Term, Error>
{
    let mut iter = exprs.iter();

    while let Some(ref expr) = iter.next() {
        match **expr {
            Variable(i) => output.push(Var(i)),
            Abstraction => stack.push(Abstraction),
            Sequence(ref exprs) => {
                let mut stack2 = Vec::new();
                let mut output2 = Vec::new();
                let subexpr = try!(fold_exprs(&exprs, &mut stack2, &mut output2));
                output.push(subexpr)
            }
        }
    }

    let mut ret = try!(fold_terms(output.drain(..).collect()));

    while let Some(Abstraction) = stack.pop() {
        ret = abs(ret);
    }

    Ok(ret)
}

fn fold_terms(mut terms: Vec<Term>) -> Result<Term, Error> {
    if terms.len() > 1 {
        let fst = terms.remove(0);
        Ok( terms.into_iter().fold(fst, |acc, t| app(acc, t)) )
    } else if terms.len() == 1 {
        Ok( terms.pop().unwrap() )
    } else {
        Err(EmptyExpression)
    }
}

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

    #[test]
    fn tokenization_error() {
        assert_eq!(tokenize(&"λλx2"), Err(InvalidCharacter((4, 'x'))))
    }

    #[test]
    fn tokenization_success() {
        let quine = "λ 1 ( (λ 1 1) (λ λ λ λ λ 1 4 (3 (5 5) 2) ) ) 1";
        let tokens = tokenize(&quine);

        assert!(tokens.is_ok());
        assert_eq!(tokens.unwrap(), vec![Lambda, Number(1), Lparen, Lparen, Lambda, Number(1),
            Number(1), Rparen, Lparen, Lambda, Lambda, Lambda, Lambda, Lambda, Number(1),
            Number(4), Lparen, Number(3), Lparen, Number(5), Number(5), Rparen, Number(2),
            Rparen, Rparen, Rparen, Number(1)]);
    }

    #[test]
    fn alternative_lambda_parsing() {
        assert_eq!(parse(&"\\\\\\2(321)"), parse(&"λλλ2(321)"))
    }

    #[test]
    fn succ_ast() {
        let tokens = tokenize(&"λλλ2(321)").unwrap();
        let ast = get_ast(&tokens);

        assert_eq!(ast,
            Ok(Sequence(vec![
                Abstraction,
                Abstraction,
                Abstraction,
                Variable(2),
                Sequence(vec![
                    Variable(3),
                    Variable(2),
                    Variable(1)
                ])
            ])
        ));
    }

    #[test]
    fn parse_y() {
        let y = "λ(λ2(11))(λ2(11))";
        assert_eq!(parse(&y).expect("parsing Y failed!"),
            abs(
                app(
                    abs(
                        app(
                            Var(2),
                            app(Var(1), Var(1))
                        )
                    ),
                    abs(
                        app(
                            Var(2),
                            app(Var(1), Var(1))
                        )
                    )
                )
            )
        );
    }

    #[test]
    fn parse_quine() {
        let quine = "λ1((λ11)(λλλλλ14(3(55)2)))1";
        assert_eq!(parse(&quine).expect("parsing QUINE failed!"),
            abs(app(app(Var(1), app(abs(app(Var(1), Var(1))), abs(abs(abs(abs(abs(app(app(Var(1),
            Var(4)), app(app(Var(3), app(Var(5), Var(5))), Var(2)))))))))), Var(1)))
        );
    }

    #[test]
    fn parse_blc() {
        let blc = "(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))(1(2(λ12))\
                   (λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))";
        assert_eq!(parse(&blc).expect("parsing BLC failed!"),
            app(app(abs(app(Var(1), Var(1))), abs(abs(abs(app(app(app(Var(1),
            abs(abs(abs(abs(app(Var(3), abs(app(app(Var(5), app(Var(3), abs(app(app(Var(2),
            app(Var(3), abs(abs(app(Var(3), abs(app(app(Var(1), Var(2)), Var(3)))))))), app(Var(4),
            abs(app(Var(4), abs(app(app(Var(3), Var(1)), app(Var(2), Var(1))))))))))),
            app(app(Var(1), app(Var(2), abs(app(Var(1), Var(2))))), abs(app(app(Var(4),
            abs(app(Var(4), abs(app(Var(2), app(Var(1), Var(4))))))), Var(5)))))))))))),
            app(Var(3), Var(3))), Var(2)))))), abs(app(Var(1), app(abs(app(Var(1), Var(1))),
            abs(app(Var(1), Var(1)))))))
        );
    }
}
<|endoftext|>