<commit_before>extern crate iron;
extern crate staticfile;
extern crate mount;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate rustfmt;
extern crate json_sample_shared;
extern crate error_chain;

use std::path::Path;

use iron::prelude::*;
use iron::status;
use staticfile::Static;
use mount::Mount;
use rustfmt::config::{Config, WriteMode};
use error_chain::ChainedError;

use json_sample_shared::{codegen_from_sample, SampleSource};

#[derive(Debug, Deserialize)]
struct ReqBody {
    name: String,
    input: String
}

macro_rules! handle {
    ($result:expr, $err_handler:expr) => (handle!($result, _err => $err_handler));
    ($result:expr, $err_id:ident => $err_handler:expr) => (match $result {
        ::std::result::Result::Ok(val) => val,
        ::std::result::Result::Err($err_id) => return ::std::result::Result::Ok(
            ::iron::Response::with((::iron::status::BadRequest, $err_handler)))
    });
}

fn handle_codegen_request(req: &mut Request) -> IronResult<Response> {
    let req_body: ReqBody = handle!(serde_json::de::from_reader(&mut req.body),
        "Error: Request body was invalid JSON");
    let tokens = handle!(codegen_from_sample(&req_body.name, &SampleSource::Text(&req_body.input)),
        err => format!("{}", err.display()));

    let input = rustfmt::Input::Text(String::from(tokens.as_str()));
    let mut output: Vec<u8> = Vec::new();
    let mut config = Config::default();
    config.write_mode = WriteMode::Plain;
    handle!(rustfmt::format_input(input, &config, Some(&mut output)),
        err => format!("Error formatting output with rustfmt: {:?}", err));

    let s = String::from_utf8_lossy(&output);
    let formatted = fix_rustfmt_issues(&s);

    Ok(Response::with((status::Ok, formatted)))
}

fn fix_rustfmt_issues(input: &str) -> String {
    let mut output = String::new();

    for line in input.lines() {
        if line.starts_with('#') {
            for c in line.chars() {
                match c {
                    ' ' => {},
                    ',' => { output.push_str(", "); }
                    _ => { output.push(c); }
                }
            }
            output.push('\n');
        } else {
            output.push_str(line);
            output.push('\n');
            if line == "}" {
                output.push('\n');
            }
        }
    }

    output
}

fn main() {
    let mut mount = Mount::new();

    mount.mount("/", Static::new(Path::new("static/")));
    mount.mount("/api", handle_codegen_request);

    let host = "localhost:3000";
    let _server = Iron::new(mount).http(host).unwrap();
    println!("Serving on {}", host);
}
<commit_msg>web: Print debug info and read host from env<commit_after>extern crate iron;
extern crate staticfile;
extern crate mount;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate rustfmt;
extern crate json_sample_shared;
extern crate error_chain;

use std::path::Path;

use iron::prelude::*;
use iron::status;
use staticfile::Static;
use mount::Mount;
use rustfmt::config::{Config, WriteMode};
use error_chain::ChainedError;
use std::env;

use json_sample_shared::{codegen_from_sample, SampleSource};

#[derive(Debug, Deserialize)]
struct ReqBody {
    name: String,
    input: String
}

macro_rules! handle {
    ($result:expr, $err_handler:expr) => (handle!($result, _err => $err_handler));
    ($result:expr, $err_id:ident => $err_handler:expr) => (match $result {
        ::std::result::Result::Ok(val) => val,
        ::std::result::Result::Err($err_id) => return ::std::result::Result::Ok(
            ::iron::Response::with((::iron::status::BadRequest, $err_handler)))
    });
}

fn handle_codegen_request(req: &mut Request) -> IronResult<Response> {
    let req_body: ReqBody = handle!(serde_json::de::from_reader(&mut req.body),
        "Error: Request body was invalid JSON");
    let tokens = handle!(codegen_from_sample(&req_body.name, &SampleSource::Text(&req_body.input)),
        err => format!("{}", err.display()));

    let input = rustfmt::Input::Text(String::from(tokens.as_str()));
    let mut output: Vec<u8> = Vec::new();
    let mut config = Config::default();
    config.write_mode = WriteMode::Plain;
    handle!(rustfmt::format_input(input, &config, Some(&mut output)),
        err => format!("Error formatting output with rustfmt: {:?}", err));

    let s = String::from_utf8_lossy(&output);
    let formatted = fix_rustfmt_issues(&s);

    Ok(Response::with((status::Ok, formatted)))
}

fn fix_rustfmt_issues(input: &str) -> String {
    let mut output = String::new();

    for line in input.lines() {
        if line.starts_with('#') {
            for c in line.chars() {
                match c {
                    ' ' => {},
                    ',' => { output.push_str(", "); }
                    _ => { output.push(c); }
                }
            }
            output.push('\n');
        } else {
            output.push_str(line);
            output.push('\n');
            if line == "}" {
                output.push('\n');
            }
        }
    }

    output
}

fn main() {
    let mut mount = Mount::new();

    let p = env::current_dir().unwrap();
    println!("Working directory is {}", p.display());
    let static_path = Path::new("static/");
    let canonical_static = static_path.canonicalize().unwrap();
    println!("Looking for static files in {}", canonical_static.display());

    mount.mount("/", Static::new(static_path));
    mount.mount("/api", handle_codegen_request);

    let host = env::var("JSONSAMPLE_HOST").unwrap_or_else(|_| String::from("0.0.0.0:5555"));
    let _server = Iron::new(mount).http(&host as &str).unwrap();
    println!("Serving on http://{}", host);
}
<|endoftext|>


<commit_before>use rocksdb;
use kite::schema::FieldRef;
use byteorder::{ByteOrder, BigEndian};

use RocksDBIndexReader;
use key_builder::KeyBuilder;
use doc_id_set::DocIdSet;
use term_dictionary::TermRef;
use document_index::DocRef;

#[derive(Debug)]
pub enum SegmentReadError {
    RocksDB(rocksdb::Error),
}

impl From<SegmentReadError> for String {
    fn from(e: SegmentReadError) -> String {
        match e {
            SegmentReadError::RocksDB(e) => e.into(),
        }
    }
}

pub trait Segment {
    fn load_statistic(&self, stat_name: &[u8]) -> Result<Option<i64>, SegmentReadError>;
    fn load_stored_field_value_raw(&self, doc_ord: u16, field_ref: FieldRef, value_type: &[u8]) -> Result<Option<Vec<u8>>, SegmentReadError>;
    fn load_term_directory(&self, field_ref: FieldRef, term_ref: TermRef) -> Result<Option<DocIdSet>, SegmentReadError>;
    fn load_deletion_list(&self) -> Result<Option<DocIdSet>, SegmentReadError>;
    fn id(&self) -> u32;

    fn doc_ref(&self, ord: u16) -> DocRef {
        DocRef::from_segment_ord(self.id(), ord)
    }
}

pub struct RocksDBSegment<'a> {
    reader: &'a RocksDBIndexReader<'a>,
    id: u32,
}

impl<'a> RocksDBSegment<'a> {
    pub fn new(reader: &'a RocksDBIndexReader, id: u32) -> RocksDBSegment<'a> {
        RocksDBSegment {
            reader: reader,
            id: id,
        }
    }
}

impl<'a> Segment for RocksDBSegment<'a> {
    fn id(&self) -> u32 {
        self.id
    }

    fn load_statistic(&self, stat_name: &[u8]) -> Result<Option<i64>, SegmentReadError> {
        let kb = KeyBuilder::segment_stat(self.id, stat_name);
        let val = try!(self.reader.snapshot.get(&kb.key())).map(|val| BigEndian::read_i64(&val));
        Ok(val)
    }

    fn load_stored_field_value_raw(&self, doc_ord: u16, field_ref: FieldRef, value_type: &[u8]) -> Result<Option<Vec<u8>>, SegmentReadError> {
        let kb = KeyBuilder::stored_field_value(self.id, doc_ord, field_ref.ord(), value_type);
        let val = try!(self.reader.snapshot.get(&kb.key()));
        Ok(val.map(|v| v.to_vec()))
    }

    fn load_term_directory(&self, field_ref: FieldRef, term_ref: TermRef) -> Result<Option<DocIdSet>, SegmentReadError> {
        let kb = KeyBuilder::segment_dir_list(self.id, field_ref.ord(), term_ref.ord());
        let doc_id_set = try!(self.reader.snapshot.get(&kb.key())).map(|doc_id_set| DocIdSet::FromRDB(doc_id_set));
        Ok(doc_id_set)
    }

    fn load_deletion_list(&self) -> Result<Option<DocIdSet>, SegmentReadError> {
        let kb = KeyBuilder::segment_del_list(self.id);
        let doc_id_set = try!(self.reader.snapshot.get(&kb.key())).map(|doc_id_set| DocIdSet::FromRDB(doc_id_set));
        Ok(doc_id_set)
    }
}

impl From<rocksdb::Error> for SegmentReadError {
    fn from(e: rocksdb::Error) -> SegmentReadError {
        SegmentReadError::RocksDB(e)
    }
}
<commit_msg>Make SegmentReadError generic<commit_after>use rocksdb;
use kite::schema::FieldRef;
use byteorder::{ByteOrder, BigEndian};

use RocksDBIndexReader;
use key_builder::KeyBuilder;
use doc_id_set::DocIdSet;
use term_dictionary::TermRef;
use document_index::DocRef;

// TODO: Use generics instead of casting to string
#[derive(Debug)]
pub struct SegmentReadError {
    message: String,
}

impl From<SegmentReadError> for String {
    fn from(e: SegmentReadError) -> String {
        e.message
    }
}

pub trait Segment {
    fn load_statistic(&self, stat_name: &[u8]) -> Result<Option<i64>, SegmentReadError>;
    fn load_stored_field_value_raw(&self, doc_ord: u16, field_ref: FieldRef, value_type: &[u8]) -> Result<Option<Vec<u8>>, SegmentReadError>;
    fn load_term_directory(&self, field_ref: FieldRef, term_ref: TermRef) -> Result<Option<DocIdSet>, SegmentReadError>;
    fn load_deletion_list(&self) -> Result<Option<DocIdSet>, SegmentReadError>;
    fn id(&self) -> u32;

    fn doc_ref(&self, ord: u16) -> DocRef {
        DocRef::from_segment_ord(self.id(), ord)
    }
}

pub struct RocksDBSegment<'a> {
    reader: &'a RocksDBIndexReader<'a>,
    id: u32,
}

impl<'a> RocksDBSegment<'a> {
    pub fn new(reader: &'a RocksDBIndexReader, id: u32) -> RocksDBSegment<'a> {
        RocksDBSegment {
            reader: reader,
            id: id,
        }
    }
}

impl<'a> Segment for RocksDBSegment<'a> {
    fn id(&self) -> u32 {
        self.id
    }

    fn load_statistic(&self, stat_name: &[u8]) -> Result<Option<i64>, SegmentReadError> {
        let kb = KeyBuilder::segment_stat(self.id, stat_name);
        let val = try!(self.reader.snapshot.get(&kb.key())).map(|val| BigEndian::read_i64(&val));
        Ok(val)
    }

    fn load_stored_field_value_raw(&self, doc_ord: u16, field_ref: FieldRef, value_type: &[u8]) -> Result<Option<Vec<u8>>, SegmentReadError> {
        let kb = KeyBuilder::stored_field_value(self.id, doc_ord, field_ref.ord(), value_type);
        let val = try!(self.reader.snapshot.get(&kb.key()));
        Ok(val.map(|v| v.to_vec()))
    }

    fn load_term_directory(&self, field_ref: FieldRef, term_ref: TermRef) -> Result<Option<DocIdSet>, SegmentReadError> {
        let kb = KeyBuilder::segment_dir_list(self.id, field_ref.ord(), term_ref.ord());
        let doc_id_set = try!(self.reader.snapshot.get(&kb.key())).map(|doc_id_set| DocIdSet::FromRDB(doc_id_set));
        Ok(doc_id_set)
    }

    fn load_deletion_list(&self) -> Result<Option<DocIdSet>, SegmentReadError> {
        let kb = KeyBuilder::segment_del_list(self.id);
        let doc_id_set = try!(self.reader.snapshot.get(&kb.key())).map(|doc_id_set| DocIdSet::FromRDB(doc_id_set));
        Ok(doc_id_set)
    }
}

impl From<rocksdb::Error> for SegmentReadError {
    fn from(e: rocksdb::Error) -> SegmentReadError {
        SegmentReadError {
            message: e.into()
        }
    }
}
<|endoftext|>


<commit_before>#![feature(core,no_std)]
#![no_main]
#![no_std]

extern crate core;
extern crate common;
extern crate support;
extern crate hil;
extern crate platform;

mod apps;

pub mod process;
pub mod syscall;

#[no_mangle]
pub extern fn main() {
    use core::prelude::*;
    use process::Process;

    let mut platform = unsafe {
        platform::init()
    };

    let app1 = unsafe { Process::create(apps::app1_init).unwrap() };

    let mut process = app1;

    unsafe {
        match process.state {
            process::State::Running => {
                process.switch_to();
            }
            process::State::Waiting => {
                match process.callbacks.dequeue() {
                    None => { },
                    Some(cb) => {
                        process.state = process::State::Running;
                        process.switch_to_callback(cb);
                    }
                }
            }
        }
        match process.svc_number() {
            Some(syscall::WAIT) => {
                platform.with_driver(1, |console| {
                    console.map(|c| c. command(0, 'w' as usize));
                });
                process.state = process::State::Waiting;
                process.pop_syscall_stack();
                // TODO(alevy): iterate `process` to next available app
            },
            Some(syscall::SUBSCRIBE) => {
                platform.with_driver(1, |console| {
                    console.map(|c| c. command(0, 's' as usize));
                });
                let res = platform.with_driver(process.r0(), |driver| {
                    match driver {
                        Some(d) => d.subscribe(process.r1(),
                                                    process.r2()),
                        None => -1
                    }
                });
                process.set_r0(res);
            },
            Some(syscall::COMMAND) => {
                platform.with_driver(1, |console| {
                    console.map(|c| c. command(0, 'c' as usize));
                });
                let res = platform.with_driver(process.r0(), |driver| {
                    match driver {
                        Some(d) => d.command(process.r1(),
                                             process.r2()),
                        None => -1
                    }
                });
                process.set_r0(res);
            },
            _ => {}
        }
    }

    loop {
        unsafe {
            platform.service_pending_interrupts();

            support::atomic(|| {
                if !platform.has_pending_interrupts() {
                    support::wfi();
                }
            })
        };
    }
}

<commit_msg>cleanup<commit_after>#![feature(core,no_std)]
#![no_main]
#![no_std]

extern crate core;
extern crate common;
extern crate support;
extern crate hil;
extern crate platform;

mod apps;

pub mod process;
pub mod syscall;

#[no_mangle]
pub extern fn main() {
    use core::prelude::*;
    use process::Process;

    let mut platform = unsafe {
        platform::init()
    };

    let app1 = unsafe { Process::create(apps::app1_init).unwrap() };

    let mut process = app1;

    unsafe {
        match process.state {
            process::State::Running => {
                process.switch_to();
            }
            process::State::Waiting => {
                match process.callbacks.dequeue() {
                    None => { },
                    Some(cb) => {
                        process.state = process::State::Running;
                        process.switch_to_callback(cb);
                    }
                }
            }
        }
        match process.svc_number() {
            Some(syscall::WAIT) => {
                process.state = process::State::Waiting;
                process.pop_syscall_stack();
                // TODO(alevy): iterate `process` to next available app
            },
            Some(syscall::SUBSCRIBE) => {
                let res = platform.with_driver(process.r0(), |driver| {
                    match driver {
                        Some(d) => d.subscribe(process.r1(),
                                                    process.r2()),
                        None => -1
                    }
                });
                process.set_r0(res);
            },
            Some(syscall::COMMAND) => {
                let res = platform.with_driver(process.r0(), |driver| {
                    match driver {
                        Some(d) => d.command(process.r1(),
                                             process.r2()),
                        None => -1
                    }
                });
                process.set_r0(res);
            },
            _ => {}
        }
    }

    loop {
        unsafe {
            platform.service_pending_interrupts();

            support::atomic(|| {
                if !platform.has_pending_interrupts() {
                    support::wfi();
                }
            })
        };
    }
}

<|endoftext|>


<commit_before>// see OSC Type Tag String: http://opensoundcontrol.org/spec-1_0
// padding: zero bytes (n*4)
pub enum OscType {
    OscInt(i32),
    OscFloat(f32),
    OscString(String), // padding
    OscBlob(Vec<u8>), // padding
    OscTimetag(u64),
    // nonstandard argument types
    // ignore them if not implemented
    OscInt64(i64), // big-endian
    OscDouble(u64),
    OscChar(u8), // padding
    OscColor(u32), // RGBA
    OscMidi(OscMidiType),
    OscTrue,
    OscFalse,
    OscNil,
    OscInf,
    OscArray(Vec<OscType>),
}

pub struct OscMidiType {
    port: u8,
    status: u8,
    data1: u8, // maybe use an enum for data?
    data2: u8,
}
<commit_msg>Add OscPacket enum<commit_after>// see OSC Type Tag String: http://opensoundcontrol.org/spec-1_0
// padding: zero bytes (n*4)
pub enum OscType {
    OscInt(i32),
    OscFloat(f32),
    OscString(String), // padding
    OscBlob(Vec<u8>), // padding
    OscTimetag(u64),
    // nonstandard argument types
    // ignore them if not implemented
    OscInt64(i64), // big-endian
    OscDouble(u64),
    OscChar(u8), // padding
    OscColor(u32), // RGBA
    OscMidi(OscMidiType),
    OscTrue,
    OscFalse,
    OscNil,
    OscInf,
    OscArray(Vec<OscType>),
}

pub struct OscMidiType {
    port: u8,
    status: u8,
    data1: u8, // maybe use an enum for data?
    data2: u8,
}

/// An *osc packet* can contain an *osc message* or a bundle of nested messages
/// which is called *osc bundle*.
pub enum OscPacket {
    OscMessage,
    OscBundle,
}
<|endoftext|>


<commit_before>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use libc::{
    _exit, c_int, c_void, siginfo_t, SIGBUS, SIGHUP, SIGILL, SIGPIPE, SIGSEGV, SIGSYS, SIGXCPU,
    SIGXFSZ,
};

use logger::{error, Metric, METRICS};
use utils::signal::register_signal_handler;

// The offset of `si_syscall` (offending syscall identifier) within the siginfo structure
// expressed as an `(u)int*`.
// Offset `6` for an `i32` field means that the needed information is located at `6 * sizeof(i32)`.
// See /usr/include/linux/signal.h for the C struct definition.
// See https://github.com/rust-lang/libc/issues/716 for why the offset is different in Rust.
const SI_OFF_SYSCALL: isize = 6;

const SYS_SECCOMP_CODE: i32 = 1;

macro_rules! generate_handler {
    ($fn_name:ident ,$signal_name:ident, $exit_code:ident, $signal_metric:expr, $body:ident) => {
        #[inline(always)]
        extern "C" fn $fn_name(num: c_int, info: *mut siginfo_t, _unused: *mut c_void) {
            // Safe because we're just reading some fields from a supposedly valid argument.
            let si_signo = unsafe { (*info).si_signo };
            let si_code = unsafe { (*info).si_code };

            if num != si_signo || num != $signal_name {
                // Safe because we're terminating the process anyway.
                unsafe { _exit(i32::from(super::FC_EXIT_CODE_UNEXPECTED_ERROR)) };
            }
            $signal_metric.inc();

            $body(si_code, info);

            error!(
                "Shutting down VM after intercepting signal {}, code {}.",
                si_signo, si_code
            );
            // Write the metrics before exiting.
            if let Err(e) = METRICS.write() {
                error!("Failed to write metrics while stopping: {}", e);
            }

            // Safe because we're terminating the process anyway. We don't actually do anything when
            // running unit tests.
            #[cfg(not(test))]
            unsafe {
                _exit(i32::from(match si_signo {
                    $signal_name => super::$exit_code,
                    _ => super::FC_EXIT_CODE_UNEXPECTED_ERROR,
                }))
            };
        }
    };
}

fn log_sigsys_err(si_code: c_int, info: *mut siginfo_t) {
    if si_code != SYS_SECCOMP_CODE as i32 {
        // Safe because we're terminating the process anyway.
        unsafe { _exit(i32::from(super::FC_EXIT_CODE_UNEXPECTED_ERROR)) };
    }

    // Other signals which might do async unsafe things incompatible with the rest of this
    // function are blocked due to the sa_mask used when registering the signal handler.
    let syscall = unsafe { *(info as *const i32).offset(SI_OFF_SYSCALL) as usize };
    error!(
        "Shutting down VM after intercepting a bad syscall ({}).",
        syscall
    );
}

fn empty_fn(_si_code: c_int, _info: *mut siginfo_t) {}

generate_handler!(
    sigxfsz_handler,
    SIGXFSZ,
    FC_EXIT_CODE_SIGXFSZ,
    METRICS.signals.sigxfsz,
    empty_fn
);

generate_handler!(
    sigxcpu_handler,
    SIGXCPU,
    FC_EXIT_CODE_SIGXCPU,
    METRICS.signals.sigxcpu,
    empty_fn
);

generate_handler!(
    sigbus_handler,
    SIGBUS,
    FC_EXIT_CODE_SIGBUS,
    METRICS.signals.sigbus,
    empty_fn
);

generate_handler!(
    sigsegv_handler,
    SIGSEGV,
    FC_EXIT_CODE_SIGSEGV,
    METRICS.signals.sigsegv,
    empty_fn
);

generate_handler!(
    sigpipe_handler,
    SIGPIPE,
    FC_EXIT_CODE_SIGPIPE,
    METRICS.signals.sigpipe,
    empty_fn
);

generate_handler!(
    sigsys_handler,
    SIGSYS,
    FC_EXIT_CODE_BAD_SYSCALL,
    METRICS.seccomp.num_faults,
    log_sigsys_err
);

generate_handler!(
    sighup_handler,
    SIGHUP,
    FC_EXIT_CODE_SIGHUP,
    METRICS.signals.sighup,
    empty_fn
);
generate_handler!(
    sigill_handler,
    SIGILL,
    FC_EXIT_CODE_SIGILL,
    METRICS.signals.sigill,
    empty_fn
);
/// Registers all the required signal handlers.
///
/// Custom handlers are installed for: `SIGBUS`, `SIGSEGV`, `SIGSYS`
/// `SIGXFSZ` `SIGXCPU` `SIGPIPE` `SIGHUP` and `SIGILL`.
pub fn register_signal_handlers() -> utils::errno::Result<()> {
    // Call to unsafe register_signal_handler which is considered unsafe because it will
    // register a signal handler which will be called in the current thread and will interrupt
    // whatever work is done on the current thread, so we have to keep in mind that the registered
    // signal handler must only do async-signal-safe operations.
    register_signal_handler(SIGSYS, sigsys_handler)?;
    register_signal_handler(SIGBUS, sigbus_handler)?;
    register_signal_handler(SIGSEGV, sigsegv_handler)?;
    register_signal_handler(SIGXFSZ, sigxfsz_handler)?;
    register_signal_handler(SIGXCPU, sigxcpu_handler)?;
    register_signal_handler(SIGPIPE, sigpipe_handler)?;
    register_signal_handler(SIGHUP, sighup_handler)?;
    register_signal_handler(SIGILL, sigill_handler)?;
    Ok(())
}

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

    use libc::{cpu_set_t, syscall};
    use std::{convert::TryInto, mem, process, thread};

    use seccomp::{allow_syscall, SeccompAction, SeccompFilter};

    // This function is used when running unit tests, so all the unsafes are safe.
    fn cpu_count() -> usize {
        let mut cpuset: cpu_set_t = unsafe { mem::zeroed() };
        unsafe {
            libc::CPU_ZERO(&mut cpuset);
        }
        let ret = unsafe {
            libc::sched_getaffinity(
                0,
                mem::size_of::<cpu_set_t>(),
                &mut cpuset as *mut cpu_set_t,
            )
        };
        assert_eq!(ret, 0);

        let mut num = 0;
        for i in 0..libc::CPU_SETSIZE as usize {
            if unsafe { libc::CPU_ISSET(i, &cpuset) } {
                num += 1;
            }
        }
        num
    }

    #[test]
    fn test_signal_handler() {
        let child = thread::spawn(move || {
            assert!(register_signal_handlers().is_ok());

            let filter = SeccompFilter::new(
                vec![
                    allow_syscall(libc::SYS_brk),
                    allow_syscall(libc::SYS_exit),
                    allow_syscall(libc::SYS_futex),
                    allow_syscall(libc::SYS_getpid),
                    allow_syscall(libc::SYS_munmap),
                    allow_syscall(libc::SYS_kill),
                    allow_syscall(libc::SYS_rt_sigprocmask),
                    allow_syscall(libc::SYS_rt_sigreturn),
                    allow_syscall(libc::SYS_sched_getaffinity),
                    allow_syscall(libc::SYS_set_tid_address),
                    allow_syscall(libc::SYS_sigaltstack),
                    allow_syscall(libc::SYS_write),
                ]
                .into_iter()
                .collect(),
                SeccompAction::Trap,
            )
            .unwrap();

            assert!(SeccompFilter::apply(filter.try_into().unwrap()).is_ok());
            assert_eq!(METRICS.seccomp.num_faults.count(), 0);

            // Call the blacklisted `SYS_mkdirat`.
            unsafe { syscall(libc::SYS_mkdirat, "/foo/bar\0") };

            // Call SIGBUS signal handler.
            assert_eq!(METRICS.signals.sigbus.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGBUS);
            }

            // Call SIGSEGV signal handler.
            assert_eq!(METRICS.signals.sigsegv.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGSEGV);
            }

            // Call SIGXFSZ signal handler.
            assert_eq!(METRICS.signals.sigxfsz.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGXFSZ);
            }

            // Call SIGXCPU signal handler.
            assert_eq!(METRICS.signals.sigxcpu.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGXCPU);
            }

            // Call SIGPIPE signal handler.
            assert_eq!(METRICS.signals.sigpipe.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGPIPE);
            }

            // Call SIGHUP signal handler.
            assert_eq!(METRICS.signals.sighup.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGHUP);
            }

            // Call SIGILL signal handler.
            assert_eq!(METRICS.signals.sigill.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGILL);
            }
        });
        assert!(child.join().is_ok());

        // Sanity check.
        assert!(cpu_count() > 0);
        // Kcov somehow messes with our handler getting the SIGSYS signal when a bad syscall
        // is caught, so the following assertion no longer holds. Ideally, we'd have a surefire
        // way of either preventing this behaviour, or detecting for certain whether this test is
        // run by kcov or not. The best we could do so far is to look at the perceived number of
        // available CPUs. Kcov seems to make a single CPU available to the process running the
        // tests, so we use this as an heuristic to decide if we check the assertion.
        if cpu_count() > 1 {
            // The signal handler should let the program continue during unit tests.
            assert!(METRICS.seccomp.num_faults.count() >= 1);
        }
        assert!(METRICS.signals.sigbus.count() >= 1);
        assert!(METRICS.signals.sigsegv.count() >= 1);
        assert!(METRICS.signals.sigxfsz.count() >= 1);
        assert!(METRICS.signals.sigxcpu.count() >= 1);
        assert!(METRICS.signals.sigpipe.count() >= 1);
        assert!(METRICS.signals.sighup.count() >= 1);
        assert!(METRICS.signals.sigill.count() >= 1);
    }
}
<commit_msg>temporarily disable assert for aarch64<commit_after>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use libc::{
    _exit, c_int, c_void, siginfo_t, SIGBUS, SIGHUP, SIGILL, SIGPIPE, SIGSEGV, SIGSYS, SIGXCPU,
    SIGXFSZ,
};

use logger::{error, Metric, METRICS};
use utils::signal::register_signal_handler;

// The offset of `si_syscall` (offending syscall identifier) within the siginfo structure
// expressed as an `(u)int*`.
// Offset `6` for an `i32` field means that the needed information is located at `6 * sizeof(i32)`.
// See /usr/include/linux/signal.h for the C struct definition.
// See https://github.com/rust-lang/libc/issues/716 for why the offset is different in Rust.
const SI_OFF_SYSCALL: isize = 6;

const SYS_SECCOMP_CODE: i32 = 1;

macro_rules! generate_handler {
    ($fn_name:ident ,$signal_name:ident, $exit_code:ident, $signal_metric:expr, $body:ident) => {
        #[inline(always)]
        extern "C" fn $fn_name(num: c_int, info: *mut siginfo_t, _unused: *mut c_void) {
            // Safe because we're just reading some fields from a supposedly valid argument.
            let si_signo = unsafe { (*info).si_signo };
            let si_code = unsafe { (*info).si_code };

            if num != si_signo || num != $signal_name {
                // Safe because we're terminating the process anyway.
                unsafe { _exit(i32::from(super::FC_EXIT_CODE_UNEXPECTED_ERROR)) };
            }
            $signal_metric.inc();

            $body(si_code, info);

            error!(
                "Shutting down VM after intercepting signal {}, code {}.",
                si_signo, si_code
            );
            // Write the metrics before exiting.
            if let Err(e) = METRICS.write() {
                error!("Failed to write metrics while stopping: {}", e);
            }

            // Safe because we're terminating the process anyway. We don't actually do anything when
            // running unit tests.
            #[cfg(not(test))]
            unsafe {
                _exit(i32::from(match si_signo {
                    $signal_name => super::$exit_code,
                    _ => super::FC_EXIT_CODE_UNEXPECTED_ERROR,
                }))
            };
        }
    };
}

fn log_sigsys_err(si_code: c_int, info: *mut siginfo_t) {
    if si_code != SYS_SECCOMP_CODE as i32 {
        // Safe because we're terminating the process anyway.
        unsafe { _exit(i32::from(super::FC_EXIT_CODE_UNEXPECTED_ERROR)) };
    }

    // Other signals which might do async unsafe things incompatible with the rest of this
    // function are blocked due to the sa_mask used when registering the signal handler.
    let syscall = unsafe { *(info as *const i32).offset(SI_OFF_SYSCALL) as usize };
    error!(
        "Shutting down VM after intercepting a bad syscall ({}).",
        syscall
    );
}

fn empty_fn(_si_code: c_int, _info: *mut siginfo_t) {}

generate_handler!(
    sigxfsz_handler,
    SIGXFSZ,
    FC_EXIT_CODE_SIGXFSZ,
    METRICS.signals.sigxfsz,
    empty_fn
);

generate_handler!(
    sigxcpu_handler,
    SIGXCPU,
    FC_EXIT_CODE_SIGXCPU,
    METRICS.signals.sigxcpu,
    empty_fn
);

generate_handler!(
    sigbus_handler,
    SIGBUS,
    FC_EXIT_CODE_SIGBUS,
    METRICS.signals.sigbus,
    empty_fn
);

generate_handler!(
    sigsegv_handler,
    SIGSEGV,
    FC_EXIT_CODE_SIGSEGV,
    METRICS.signals.sigsegv,
    empty_fn
);

generate_handler!(
    sigpipe_handler,
    SIGPIPE,
    FC_EXIT_CODE_SIGPIPE,
    METRICS.signals.sigpipe,
    empty_fn
);

generate_handler!(
    sigsys_handler,
    SIGSYS,
    FC_EXIT_CODE_BAD_SYSCALL,
    METRICS.seccomp.num_faults,
    log_sigsys_err
);

generate_handler!(
    sighup_handler,
    SIGHUP,
    FC_EXIT_CODE_SIGHUP,
    METRICS.signals.sighup,
    empty_fn
);
generate_handler!(
    sigill_handler,
    SIGILL,
    FC_EXIT_CODE_SIGILL,
    METRICS.signals.sigill,
    empty_fn
);
/// Registers all the required signal handlers.
///
/// Custom handlers are installed for: `SIGBUS`, `SIGSEGV`, `SIGSYS`
/// `SIGXFSZ` `SIGXCPU` `SIGPIPE` `SIGHUP` and `SIGILL`.
pub fn register_signal_handlers() -> utils::errno::Result<()> {
    // Call to unsafe register_signal_handler which is considered unsafe because it will
    // register a signal handler which will be called in the current thread and will interrupt
    // whatever work is done on the current thread, so we have to keep in mind that the registered
    // signal handler must only do async-signal-safe operations.
    register_signal_handler(SIGSYS, sigsys_handler)?;
    register_signal_handler(SIGBUS, sigbus_handler)?;
    register_signal_handler(SIGSEGV, sigsegv_handler)?;
    register_signal_handler(SIGXFSZ, sigxfsz_handler)?;
    register_signal_handler(SIGXCPU, sigxcpu_handler)?;
    register_signal_handler(SIGPIPE, sigpipe_handler)?;
    register_signal_handler(SIGHUP, sighup_handler)?;
    register_signal_handler(SIGILL, sigill_handler)?;
    Ok(())
}

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

    use libc::{cpu_set_t, syscall};
    use std::{convert::TryInto, mem, process, thread};

    use seccomp::{allow_syscall, SeccompAction, SeccompFilter};

    // This function is used when running unit tests, so all the unsafes are safe.
    fn cpu_count() -> usize {
        let mut cpuset: cpu_set_t = unsafe { mem::zeroed() };
        unsafe {
            libc::CPU_ZERO(&mut cpuset);
        }
        let ret = unsafe {
            libc::sched_getaffinity(
                0,
                mem::size_of::<cpu_set_t>(),
                &mut cpuset as *mut cpu_set_t,
            )
        };
        assert_eq!(ret, 0);

        let mut num = 0;
        for i in 0..libc::CPU_SETSIZE as usize {
            if unsafe { libc::CPU_ISSET(i, &cpuset) } {
                num += 1;
            }
        }
        num
    }

    #[test]
    fn test_signal_handler() {
        let child = thread::spawn(move || {
            assert!(register_signal_handlers().is_ok());

            let filter = SeccompFilter::new(
                vec![
                    allow_syscall(libc::SYS_brk),
                    allow_syscall(libc::SYS_exit),
                    allow_syscall(libc::SYS_futex),
                    allow_syscall(libc::SYS_getpid),
                    allow_syscall(libc::SYS_munmap),
                    allow_syscall(libc::SYS_kill),
                    allow_syscall(libc::SYS_rt_sigprocmask),
                    allow_syscall(libc::SYS_rt_sigreturn),
                    allow_syscall(libc::SYS_sched_getaffinity),
                    allow_syscall(libc::SYS_set_tid_address),
                    allow_syscall(libc::SYS_sigaltstack),
                    allow_syscall(libc::SYS_write),
                ]
                .into_iter()
                .collect(),
                SeccompAction::Trap,
            )
            .unwrap();

            assert!(SeccompFilter::apply(filter.try_into().unwrap()).is_ok());
            assert_eq!(METRICS.seccomp.num_faults.count(), 0);

            // Call the blacklisted `SYS_mkdirat`.
            unsafe { syscall(libc::SYS_mkdirat, "/foo/bar\0") };

            // Call SIGBUS signal handler.
            assert_eq!(METRICS.signals.sigbus.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGBUS);
            }

            // Call SIGSEGV signal handler.
            assert_eq!(METRICS.signals.sigsegv.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGSEGV);
            }

            // Call SIGXFSZ signal handler.
            assert_eq!(METRICS.signals.sigxfsz.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGXFSZ);
            }

            // Call SIGXCPU signal handler.
            assert_eq!(METRICS.signals.sigxcpu.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGXCPU);
            }

            // Call SIGPIPE signal handler.
            assert_eq!(METRICS.signals.sigpipe.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGPIPE);
            }

            // Call SIGHUP signal handler.
            assert_eq!(METRICS.signals.sighup.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGHUP);
            }

            // Call SIGILL signal handler.
            assert_eq!(METRICS.signals.sigill.count(), 0);
            unsafe {
                syscall(libc::SYS_kill, process::id(), SIGILL);
            }
        });
        assert!(child.join().is_ok());

        // Sanity check.
        assert!(cpu_count() > 0);
        // Kcov somehow messes with our handler getting the SIGSYS signal when a bad syscall
        // is caught, so the following assertion no longer holds. Ideally, we'd have a surefire
        // way of either preventing this behaviour, or detecting for certain whether this test is
        // run by kcov or not. The best we could do so far is to look at the perceived number of
        // available CPUs. Kcov seems to make a single CPU available to the process running the
        // tests, so we use this as an heuristic to decide if we check the assertion.
        if cpu_count() > 1 {
            // The signal handler should let the program continue during unit tests.
            assert!(METRICS.seccomp.num_faults.count() >= 1);
        }
        assert!(METRICS.signals.sigbus.count() >= 1);
        assert!(METRICS.signals.sigsegv.count() >= 1);
        assert!(METRICS.signals.sigxfsz.count() >= 1);
        assert!(METRICS.signals.sigxcpu.count() >= 1);
        assert!(METRICS.signals.sigpipe.count() >= 1);
        assert!(METRICS.signals.sighup.count() >= 1);
        // Workaround to GitHub issue 2216.
        #[cfg(not(target_arch = "aarch64"))]
        assert!(METRICS.signals.sigill.count() >= 1);
    }
}
<|endoftext|>


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

use flow::Flow;
use flow_ref::{self, FlowRef};
use std::collections::{LinkedList, linked_list};

// This needs to be reworked now that we have dynamically-sized types in Rust.
// Until then, it's just a wrapper around LinkedList.

pub struct FlowList {
    flows: LinkedList<FlowRef>,
}

pub struct FlowListIterator<'a> {
    it: linked_list::Iter<'a, FlowRef>,
}

pub struct MutFlowListIterator<'a> {
    it: linked_list::IterMut<'a, FlowRef>,
}

impl FlowList {
    /// Add an element last in the list
    ///
    /// O(1)
    pub fn push_back(&mut self, new_tail: FlowRef) {
        self.flows.push_back(new_tail);
    }

    pub fn back(&self) -> Option<&Flow> {
        self.flows.back().map(|x| &**x)
    }

    /// Add an element first in the list
    ///
    /// O(1)
    pub fn push_front(&mut self, new_head: FlowRef) {
        self.flows.push_front(new_head);
    }

    pub fn pop_front(&mut self) -> Option<FlowRef> {
        self.flows.pop_front()
    }

    pub fn front(&self) -> Option<&Flow> {
        self.flows.front().map(|x| &**x)
    }

    /// Create an empty list
    #[inline]
    pub fn new() -> FlowList {
        FlowList {
            flows: LinkedList::new(),
        }
    }

    /// Provide a forward iterator
    #[inline]
    pub fn iter(&self) -> FlowListIterator {
        FlowListIterator {
            it: self.flows.iter(),
        }
    }

    /// Provide a forward iterator with mutable references
    #[inline]
    pub fn iter_mut(&mut self) -> MutFlowListIterator {
        MutFlowListIterator {
            it: self.flows.iter_mut(),
        }
    }

    /// Provide a forward iterator with FlowRef items
    #[inline]
    pub fn iter_flow_ref_mut<'a>(&'a mut self) -> linked_list::IterMut<'a, FlowRef> {
        self.flows.iter_mut()
    }

    /// O(1)
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.flows.is_empty()
    }

    /// O(1)
    #[inline]
    pub fn len(&self) -> usize {
        self.flows.len()
    }

    #[inline]
    pub fn split_off(&mut self, i: usize) -> Self {
        FlowList {
            flows: self.flows.split_off(i)
        }
    }
}

impl<'a> Iterator for FlowListIterator<'a> {
    type Item = &'a Flow;
    #[inline]
    fn next(&mut self) -> Option<&'a Flow> {
        self.it.next().map(|x| &**x)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.it.size_hint()
    }
}

impl<'a> DoubleEndedIterator for FlowListIterator<'a> {
    fn next_back(&mut self) -> Option<&'a Flow> {
        self.it.next_back().map(|x| &**x)
    }
}

impl<'a> Iterator for MutFlowListIterator<'a> {
    type Item = &'a mut Flow;
    #[inline]
    fn next(&mut self) -> Option<&'a mut Flow> {
        self.it.next().map(flow_ref::deref_mut)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.it.size_hint()
    }
}
<commit_msg>Added DoubleEndedIterator for MutFlowListIterator<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 flow::Flow;
use flow_ref::{self, FlowRef};
use std::collections::{LinkedList, linked_list};

// This needs to be reworked now that we have dynamically-sized types in Rust.
// Until then, it's just a wrapper around LinkedList.

pub struct FlowList {
    flows: LinkedList<FlowRef>,
}

pub struct FlowListIterator<'a> {
    it: linked_list::Iter<'a, FlowRef>,
}

pub struct MutFlowListIterator<'a> {
    it: linked_list::IterMut<'a, FlowRef>,
}

impl FlowList {
    /// Add an element last in the list
    ///
    /// O(1)
    pub fn push_back(&mut self, new_tail: FlowRef) {
        self.flows.push_back(new_tail);
    }

    pub fn back(&self) -> Option<&Flow> {
        self.flows.back().map(|x| &**x)
    }

    /// Add an element first in the list
    ///
    /// O(1)
    pub fn push_front(&mut self, new_head: FlowRef) {
        self.flows.push_front(new_head);
    }

    pub fn pop_front(&mut self) -> Option<FlowRef> {
        self.flows.pop_front()
    }

    pub fn front(&self) -> Option<&Flow> {
        self.flows.front().map(|x| &**x)
    }

    /// Create an empty list
    #[inline]
    pub fn new() -> FlowList {
        FlowList {
            flows: LinkedList::new(),
        }
    }

    /// Provide a forward iterator
    #[inline]
    pub fn iter(&self) -> FlowListIterator {
        FlowListIterator {
            it: self.flows.iter(),
        }
    }

    /// Provide a forward iterator with mutable references
    #[inline]
    pub fn iter_mut(&mut self) -> MutFlowListIterator {
        MutFlowListIterator {
            it: self.flows.iter_mut(),
        }
    }

    /// Provide a forward iterator with FlowRef items
    #[inline]
    pub fn iter_flow_ref_mut<'a>(&'a mut self) -> linked_list::IterMut<'a, FlowRef> {
        self.flows.iter_mut()
    }

    /// O(1)
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.flows.is_empty()
    }

    /// O(1)
    #[inline]
    pub fn len(&self) -> usize {
        self.flows.len()
    }

    #[inline]
    pub fn split_off(&mut self, i: usize) -> Self {
        FlowList {
            flows: self.flows.split_off(i)
        }
    }
}

impl<'a> Iterator for FlowListIterator<'a> {
    type Item = &'a Flow;
    #[inline]
    fn next(&mut self) -> Option<&'a Flow> {
        self.it.next().map(|x| &**x)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.it.size_hint()
    }
}

impl<'a> DoubleEndedIterator for FlowListIterator<'a> {
    fn next_back(&mut self) -> Option<&'a Flow> {
        self.it.next_back().map(|x| &**x)
    }
}

impl<'a> DoubleEndedIterator for MutFlowListIterator<'a> {
    fn next_back(&mut self) -> Option<&'a mut Flow> {
        self.it.next_back().map(flow_ref::deref_mut)
    }
}

impl<'a> Iterator for MutFlowListIterator<'a> {
    type Item = &'a mut Flow;
    #[inline]
    fn next(&mut self) -> Option<&'a mut Flow> {
        self.it.next().map(flow_ref::deref_mut)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.it.size_hint()
    }
}
<|endoftext|>


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

use dom::bindings::codegen::BindingDeclarations::HTMLTableCaptionElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLTableCaptionElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLTableCaptionElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLTableCaptionElement {
    pub htmlelement: HTMLElement
}

impl HTMLTableCaptionElementDerived for EventTarget {
    fn is_htmltablecaptionelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLTableCaptionElementTypeId))
    }
}

impl HTMLTableCaptionElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLTableCaptionElement {
        HTMLTableCaptionElement {
            htmlelement: HTMLElement::new_inherited(HTMLTableCaptionElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLTableCaptionElement> {
        let element = HTMLTableCaptionElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLTableCaptionElementBinding::Wrap)
    }
}

pub trait HTMLTableCaptionElementMethods {
    fn Align(&self) -> DOMString;
    fn SetAlign(&mut self, _align: DOMString) -> ErrorResult;
}

impl<'a> HTMLTableCaptionElementMethods for JSRef<'a, HTMLTableCaptionElement> {
    fn Align(&self) -> DOMString {
        "".to_owned()
    }

    fn SetAlign(&mut self, _align: DOMString) -> ErrorResult {
        Ok(())
    }
}
<commit_msg>Remove needless '&mut self' from HTMLTableCaptionElementMethods.<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 dom::bindings::codegen::BindingDeclarations::HTMLTableCaptionElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLTableCaptionElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLTableCaptionElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLTableCaptionElement {
    pub htmlelement: HTMLElement
}

impl HTMLTableCaptionElementDerived for EventTarget {
    fn is_htmltablecaptionelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLTableCaptionElementTypeId))
    }
}

impl HTMLTableCaptionElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLTableCaptionElement {
        HTMLTableCaptionElement {
            htmlelement: HTMLElement::new_inherited(HTMLTableCaptionElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLTableCaptionElement> {
        let element = HTMLTableCaptionElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLTableCaptionElementBinding::Wrap)
    }
}

pub trait HTMLTableCaptionElementMethods {
    fn Align(&self) -> DOMString;
    fn SetAlign(&self, _align: DOMString) -> ErrorResult;
}

impl<'a> HTMLTableCaptionElementMethods for JSRef<'a, HTMLTableCaptionElement> {
    fn Align(&self) -> DOMString {
        "".to_owned()
    }

    fn SetAlign(&self, _align: DOMString) -> ErrorResult {
        Ok(())
    }
}
<|endoftext|>


<commit_before>use ordered_float::OrderedFloat;
use std::ops::Sub;
use std::time::Duration;
use web_sys::window;

#[derive(Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Debug)]
pub struct Instant(OrderedFloat<f64>);

impl Instant {
    pub fn now() -> Self {
        let seconds = window()
            .and_then(|w| w.performance())
            .expect("Can't measure time without a performance object")
            .now()
            / 1000.0;
        Instant(OrderedFloat(seconds))
    }
}

impl Sub for Instant {
    type Output = Duration;

    fn sub(self, rhs: Instant) -> Duration {
        let secs = (self.0).0 - (rhs.0).0;
        let nanos = ((secs % 1.0) * 1_000_000_000.0) as _;
        let secs = secs as _;
        Duration::new(secs, nanos)
    }
}
<commit_msg>Reduce overhead of JavaScript calls<commit_after>use ordered_float::OrderedFloat;
use std::ops::Sub;
use std::time::Duration;
use web_sys::window;

#[derive(Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Debug)]
pub struct Instant(OrderedFloat<f64>);

thread_local! {
    static PERFORMANCE: web_sys::Performance = window()
        .expect("No window object available")
        .performance()
        .expect("Can't measure time without a performance object");
}

impl Instant {
    pub fn now() -> Self {
        let seconds = PERFORMANCE.with(|p| p.now()) / 1000.0;
        Instant(OrderedFloat(seconds))
    }
}

impl Sub for Instant {
    type Output = Duration;

    fn sub(self, rhs: Instant) -> Duration {
        let secs = (self.0).0 - (rhs.0).0;
        let nanos = ((secs % 1.0) * 1_000_000_000.0) as _;
        let secs = secs as _;
        Duration::new(secs, nanos)
    }
}
<|endoftext|>


<commit_before>use common::util::*;

static TEST_HELLO_WORLD_SOURCE: &'static str = "hello_world.txt";
static TEST_HELLO_WORLD_DEST: &'static str = "copy_of_hello_world.txt";
static TEST_COPY_TO_FOLDER: &'static str = "hello_dir/";
static TEST_COPY_TO_FOLDER_FILE: &'static str = "hello_dir/hello_world.txt";
static TEST_COPY_FROM_FOLDER_FILE: &'static str = "hello_dir_with_file/hello_world.txt";

#[test]
fn test_cp_cp() {
    let (at, mut ucmd) = at_and_ucmd!();
    // Invoke our binary to make the copy.
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
                     .arg(TEST_HELLO_WORLD_DEST)
                     .run();

    // Check that the exit code represents a successful copy.
    let exit_success = result.success;
    assert!(exit_success);

    // Check the content of the destination file that was copied.
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}

#[test]
fn test_cp_with_dirs_t() {
    let (at, mut ucmd) = at_and_ucmd!();

    //using -t option
    let result_to_dir_t = ucmd
        .arg("-t")
        .arg(TEST_COPY_TO_FOLDER)
        .arg(TEST_HELLO_WORLD_SOURCE)
        .run();
    assert!(result_to_dir_t.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");
}

#[test]
fn test_cp_with_dirs() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    //using -t option
    let result_to_dir = scene.ucmd()
        .arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_COPY_TO_FOLDER)
        .run();
    assert!(result_to_dir.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");

    let result_from_dir = scene.ucmd()
        .arg(TEST_COPY_FROM_FOLDER_FILE)
        .arg(TEST_HELLO_WORLD_DEST)
        .run();
    assert!(result_from_dir.success);
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}
<commit_msg>cp: add test for -r/--recursive<commit_after>use common::util::*;

static TEST_HELLO_WORLD_SOURCE: &'static str = "hello_world.txt";
static TEST_HELLO_WORLD_DEST: &'static str = "copy_of_hello_world.txt";
static TEST_COPY_TO_FOLDER: &'static str = "hello_dir/";
static TEST_COPY_TO_FOLDER_FILE: &'static str = "hello_dir/hello_world.txt";
static TEST_COPY_FROM_FOLDER: &'static str = "hello_dir_with_file/";
static TEST_COPY_FROM_FOLDER_FILE: &'static str = "hello_dir_with_file/hello_world.txt";

#[test]
fn test_cp_cp() {
    let (at, mut ucmd) = at_and_ucmd!();
    // Invoke our binary to make the copy.
    let result = ucmd.arg(TEST_HELLO_WORLD_SOURCE)
                     .arg(TEST_HELLO_WORLD_DEST)
                     .run();

    // Check that the exit code represents a successful copy.
    let exit_success = result.success;
    assert!(exit_success);

    // Check the content of the destination file that was copied.
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}

#[test]
fn test_cp_recurse() {
    //let (at, mut ucmd) = at_and_ucmd!();
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    // Invoke our binary to make the copy.
    let result_to_dir = scene.ucmd()
        .arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_COPY_TO_FOLDER)
        .run();
    assert!(result_to_dir.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");

    let result = scene.ucmd()
                     .arg("-r")
                     .arg(TEST_COPY_FROM_FOLDER)
                     .arg(TEST_COPY_TO_FOLDER)
                     .run();

    assert!(result.success);
    // Check the content of the destination file that was copied.
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");
}

#[test]
fn test_cp_with_dirs_t() {
    let (at, mut ucmd) = at_and_ucmd!();

    //using -t option
    let result_to_dir_t = ucmd
        .arg("-t")
        .arg(TEST_COPY_TO_FOLDER)
        .arg(TEST_HELLO_WORLD_SOURCE)
        .run();
    assert!(result_to_dir_t.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");
}

#[test]
fn test_cp_with_dirs() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    //using -t option
    let result_to_dir = scene.ucmd()
        .arg(TEST_HELLO_WORLD_SOURCE)
        .arg(TEST_COPY_TO_FOLDER)
        .run();
    assert!(result_to_dir.success);
    assert_eq!(at.read(TEST_COPY_TO_FOLDER_FILE), "Hello, World!\n");

    let result_from_dir = scene.ucmd()
        .arg(TEST_COPY_FROM_FOLDER_FILE)
        .arg(TEST_HELLO_WORLD_DEST)
        .run();
    assert!(result_from_dir.success);
    assert_eq!(at.read(TEST_HELLO_WORLD_DEST), "Hello, World!\n");
}
<|endoftext|>


<commit_before>mod utils;

use std::str;

use clap::{App, Arg, ErrorKind};

static VERSION: &str = "clap-test v1.4.8\n";

#[test]
fn version_short() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .try_get_matches_from(vec!["myprog", "-V"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3\n");
}

#[test]
fn version_long() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .try_get_matches_from(vec!["myprog", "--version"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3\n");
}

#[test]
fn complex_version_output() {
    let mut a = App::new("clap-test").version("v1.4.8");
    let _ = a.try_get_matches_from_mut(vec![""]);

    // Now we check the output of print_version()
    assert_eq!(a.render_version(), VERSION);
}

fn prefer_user_app() -> App<'static> {
    App::new("test")
        .version("1.3")
        .arg(
            Arg::new("version1")
                .long("version")
                .short('V')
                .about("some version"),
        )
        .subcommand(
            App::new("foo").arg(
                Arg::new("version1")
                    .long("version")
                    .short('V')
                    .about("some version"),
            ),
        )
}

#[test]
fn prefer_user_version_long() {
    let m = prefer_user_app().try_get_matches_from(vec!["test", "--version"]);

    assert!(m.is_ok());
    assert!(m.unwrap().is_present("version1"));
}

#[test]
fn prefer_user_version_short() {
    let m = prefer_user_app().try_get_matches_from(vec!["test", "-V"]);

    assert!(m.is_ok());
    assert!(m.unwrap().is_present("version1"));
}

#[test]
fn prefer_user_subcmd_version_long() {
    let m = prefer_user_app().try_get_matches_from(vec!["test", "foo", "--version"]);

    assert!(m.is_ok());
    assert!(m
        .unwrap()
        .subcommand_matches("foo")
        .unwrap()
        .is_present("version1"));
}

#[test]
fn prefer_user_subcmd_version_short() {
    let m = prefer_user_app().try_get_matches_from(vec!["test", "foo", "-V"]);

    assert!(m.is_ok());
    assert!(m
        .unwrap()
        .subcommand_matches("foo")
        .unwrap()
        .is_present("version1"));
}

static OVERRIDE_VERSION_SHORT: &str = "test 1.3

USAGE:
    test

FLAGS:
    -h, --help       Prints help information
    -v, --version    Prints version information";

#[test]
fn override_version_short() {
    let app = App::new("test")
        .version("1.3")
        .mut_arg("version", |a| a.short('v'));

    let m = app.clone().try_get_matches_from(vec!["test", "-v"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3\n");

    let m = app.clone().try_get_matches_from(vec!["test", "--version"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3\n");

    assert!(utils::compare_output(
        app,
        "test -h",
        OVERRIDE_VERSION_SHORT,
        false
    ));
}

static OVERRIDE_VERSION_LONG: &str = "test 1.3

USAGE:
    test [FLAGS]

FLAGS:
    -h, --help    Prints help information
    -V, --vers    Prints version information";

#[test]
fn override_version_long() {
    let app = App::new("test")
        .version("1.3")
        .mut_arg("version", |a| a.long("vers"));

    let m = app.clone().try_get_matches_from(vec!["test", "-V"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3\n");

    let m = app.clone().try_get_matches_from(vec!["test", "--vers"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3\n");

    assert!(utils::compare_output(
        app,
        "test -h",
        OVERRIDE_VERSION_LONG,
        false
    ));
}

static OVERRIDE_VERSION_ABOUT: &str = "test 1.3

USAGE:
    test

FLAGS:
    -h, --help       Prints help information
    -V, --version    version info";

#[test]
fn override_version_about() {
    let app = App::new("test")
        .version("1.3")
        .mut_arg("version", |a| a.about("version info"));

    assert!(utils::compare_output(
        app.clone(),
        "test -h",
        OVERRIDE_VERSION_ABOUT,
        false
    ));
    assert!(utils::compare_output(
        app,
        "test --help",
        OVERRIDE_VERSION_ABOUT,
        false
    ));
}

static VERSION_ABOUT_MULTI_SC: &str = "myapp-subcmd-multi 1.0

USAGE:
    myapp subcmd multi

FLAGS:
    -h, --help       Prints help information
    -V, --version    Print custom version about text";

#[test]
fn version_about_multi_subcmd() {
    let app = App::new("myapp")
        .mut_arg("version", |a| a.about("Print custom version about text"))
        .subcommand(App::new("subcmd").subcommand(App::new("multi").version("1.0")));

    assert!(utils::compare_output(
        app.clone(),
        "myapp help subcmd multi",
        VERSION_ABOUT_MULTI_SC,
        false
    ));
    assert!(utils::compare_output(
        app.clone(),
        "myapp subcmd multi -h",
        VERSION_ABOUT_MULTI_SC,
        false
    ));
    assert!(utils::compare_output(
        app,
        "myapp subcmd multi --help",
        VERSION_ABOUT_MULTI_SC,
        false
    ));
}

static VERSION_ABOUT_MULTI_SC_OVERRIDE: &str = "myapp-subcmd-multi 1.0

USAGE:
    myapp subcmd multi

FLAGS:
    -h, --help       Prints help information
    -V, --version    Print custom version about text from multi";

#[test]
fn version_about_multi_subcmd_override() {
    let app = App::new("myapp")
        .mut_arg("version", |a| a.about("Print custom version about text"))
        .subcommand(App::new("subcmd").subcommand(
            App::new("multi").version("1.0").mut_arg("version", |a| {
                a.about("Print custom version about text from multi")
            }),
        ));

    assert!(utils::compare_output(
        app,
        "myapp help subcmd multi",
        VERSION_ABOUT_MULTI_SC_OVERRIDE,
        false
    ));
}
<commit_msg>Fix App::version/long_version test<commit_after>mod utils;

use std::str;

use clap::{App, Arg, ErrorKind};

static VERSION: &str = "clap-test v1.4.8\n";

#[test]
fn version_short() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .long_version("1.3 (abcdef12)")
        .try_get_matches_from(vec!["myprog", "-V"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3\n");
}

#[test]
fn version_long() {
    let m = App::new("test")
        .author("Kevin K.")
        .about("tests stuff")
        .version("1.3")
        .long_version("1.3 (abcdef12)")
        .try_get_matches_from(vec!["myprog", "--version"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3 (abcdef12)\n");
}

#[test]
fn complex_version_output() {
    let mut a = App::new("clap-test").version("v1.4.8");
    let _ = a.try_get_matches_from_mut(vec![""]);

    // Now we check the output of print_version()
    assert_eq!(a.render_version(), VERSION);
}

fn prefer_user_app() -> App<'static> {
    App::new("test")
        .version("1.3")
        .arg(
            Arg::new("version1")
                .long("version")
                .short('V')
                .about("some version"),
        )
        .subcommand(
            App::new("foo").arg(
                Arg::new("version1")
                    .long("version")
                    .short('V')
                    .about("some version"),
            ),
        )
}

#[test]
fn prefer_user_version_long() {
    let m = prefer_user_app().try_get_matches_from(vec!["test", "--version"]);

    assert!(m.is_ok());
    assert!(m.unwrap().is_present("version1"));
}

#[test]
fn prefer_user_version_short() {
    let m = prefer_user_app().try_get_matches_from(vec!["test", "-V"]);

    assert!(m.is_ok());
    assert!(m.unwrap().is_present("version1"));
}

#[test]
fn prefer_user_subcmd_version_long() {
    let m = prefer_user_app().try_get_matches_from(vec!["test", "foo", "--version"]);

    assert!(m.is_ok());
    assert!(m
        .unwrap()
        .subcommand_matches("foo")
        .unwrap()
        .is_present("version1"));
}

#[test]
fn prefer_user_subcmd_version_short() {
    let m = prefer_user_app().try_get_matches_from(vec!["test", "foo", "-V"]);

    assert!(m.is_ok());
    assert!(m
        .unwrap()
        .subcommand_matches("foo")
        .unwrap()
        .is_present("version1"));
}

static OVERRIDE_VERSION_SHORT: &str = "test 1.3

USAGE:
    test

FLAGS:
    -h, --help       Prints help information
    -v, --version    Prints version information";

#[test]
fn override_version_short() {
    let app = App::new("test")
        .version("1.3")
        .mut_arg("version", |a| a.short('v'));

    let m = app.clone().try_get_matches_from(vec!["test", "-v"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3\n");

    let m = app.clone().try_get_matches_from(vec!["test", "--version"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3\n");

    assert!(utils::compare_output(
        app,
        "test -h",
        OVERRIDE_VERSION_SHORT,
        false
    ));
}

static OVERRIDE_VERSION_LONG: &str = "test 1.3

USAGE:
    test [FLAGS]

FLAGS:
    -h, --help    Prints help information
    -V, --vers    Prints version information";

#[test]
fn override_version_long() {
    let app = App::new("test")
        .version("1.3")
        .mut_arg("version", |a| a.long("vers"));

    let m = app.clone().try_get_matches_from(vec!["test", "-V"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3\n");

    let m = app.clone().try_get_matches_from(vec!["test", "--vers"]);

    assert!(m.is_err());
    let err = m.unwrap_err();
    assert_eq!(err.kind, ErrorKind::DisplayVersion);
    assert_eq!(err.to_string(), "test 1.3\n");

    assert!(utils::compare_output(
        app,
        "test -h",
        OVERRIDE_VERSION_LONG,
        false
    ));
}

static OVERRIDE_VERSION_ABOUT: &str = "test 1.3

USAGE:
    test

FLAGS:
    -h, --help       Prints help information
    -V, --version    version info";

#[test]
fn override_version_about() {
    let app = App::new("test")
        .version("1.3")
        .mut_arg("version", |a| a.about("version info"));

    assert!(utils::compare_output(
        app.clone(),
        "test -h",
        OVERRIDE_VERSION_ABOUT,
        false
    ));
    assert!(utils::compare_output(
        app,
        "test --help",
        OVERRIDE_VERSION_ABOUT,
        false
    ));
}

static VERSION_ABOUT_MULTI_SC: &str = "myapp-subcmd-multi 1.0

USAGE:
    myapp subcmd multi

FLAGS:
    -h, --help       Prints help information
    -V, --version    Print custom version about text";

#[test]
fn version_about_multi_subcmd() {
    let app = App::new("myapp")
        .mut_arg("version", |a| a.about("Print custom version about text"))
        .subcommand(App::new("subcmd").subcommand(App::new("multi").version("1.0")));

    assert!(utils::compare_output(
        app.clone(),
        "myapp help subcmd multi",
        VERSION_ABOUT_MULTI_SC,
        false
    ));
    assert!(utils::compare_output(
        app.clone(),
        "myapp subcmd multi -h",
        VERSION_ABOUT_MULTI_SC,
        false
    ));
    assert!(utils::compare_output(
        app,
        "myapp subcmd multi --help",
        VERSION_ABOUT_MULTI_SC,
        false
    ));
}

static VERSION_ABOUT_MULTI_SC_OVERRIDE: &str = "myapp-subcmd-multi 1.0

USAGE:
    myapp subcmd multi

FLAGS:
    -h, --help       Prints help information
    -V, --version    Print custom version about text from multi";

#[test]
fn version_about_multi_subcmd_override() {
    let app = App::new("myapp")
        .mut_arg("version", |a| a.about("Print custom version about text"))
        .subcommand(App::new("subcmd").subcommand(
            App::new("multi").version("1.0").mut_arg("version", |a| {
                a.about("Print custom version about text from multi")
            }),
        ));

    assert!(utils::compare_output(
        app,
        "myapp help subcmd multi",
        VERSION_ABOUT_MULTI_SC_OVERRIDE,
        false
    ));
}
<|endoftext|>


<commit_before>use prolog::ast::*;
use prolog::codegen::*;
use prolog::debray_allocator::*;
use prolog::machine::*;
use prolog::prolog_parser::*;

use termion::raw::IntoRawMode;
use termion::input::TermRead;
use termion::event::Key;

use std::io::{Write, stdin, stdout};
use std::fmt;
use std::mem::swap;

impl fmt::Display for Constant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Constant::Atom(ref atom) =>
                write!(f, "{}", atom),
            &Constant::EmptyList =>
                write!(f, "[]"),
            &Constant::UInt64(integer) =>
                write!(f, "u{}", integer)
        }
    }
}

impl fmt::Display for FactInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &FactInstruction::GetConstant(Level::Shallow, ref constant, ref r) =>
                write!(f, "get_constant {}, A{}", constant, r.reg_num()),
            &FactInstruction::GetConstant(Level::Deep, ref constant, ref r) =>
                write!(f, "get_constant {}, {}", constant, r),
            &FactInstruction::GetList(Level::Shallow, ref r) =>
                write!(f, "get_list A{}", r.reg_num()),
            &FactInstruction::GetList(Level::Deep, ref r) =>
                write!(f, "get_list {}", r),
            &FactInstruction::GetStructure(Level::Deep, ref name, ref arity, ref r) =>
                write!(f, "get_structure {}/{}, {}", name, arity, r),
            &FactInstruction::GetStructure(Level::Shallow, ref name, ref arity, ref r) =>
                write!(f, "get_structure {}/{}, A{}", name, arity, r.reg_num()),
            &FactInstruction::GetValue(ref x, ref a) =>
                write!(f, "get_value {}, A{}", x, a),
            &FactInstruction::GetVariable(ref x, ref a) =>
                write!(f, "get_variable {}, A{}", x, a),
            &FactInstruction::UnifyConstant(ref constant) =>
                write!(f, "unify_constant {}", constant),
            &FactInstruction::UnifyVariable(ref r) =>
                write!(f, "unify_variable {}", r),
            &FactInstruction::UnifyLocalValue(ref r) =>
                write!(f, "unify_local_value {}", r),
            &FactInstruction::UnifyValue(ref r) =>
                write!(f, "unify_value {}", r),
            &FactInstruction::UnifyVoid(n) =>
                write!(f, "unify_void {}", n)
        }
    }
}

impl fmt::Display for QueryInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &QueryInstruction::GetVariable(ref x, ref a) =>
                write!(f, "get_variable {}, A{}", x, a),
            &QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
                write!(f, "put_constant {}, A{}", constant, r.reg_num()),
            &QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) =>
                write!(f, "put_constant {}, {}", constant, r),
            &QueryInstruction::PutList(Level::Shallow, ref r) =>
                write!(f, "put_list A{}", r.reg_num()),
            &QueryInstruction::PutList(Level::Deep, ref r) =>
                write!(f, "put_list {}", r),
            &QueryInstruction::PutStructure(Level::Deep, ref name, ref arity, ref r) =>
                write!(f, "put_structure {}/{}, {}", name, arity, r),
            &QueryInstruction::PutStructure(Level::Shallow, ref name, ref arity, ref r) =>
                write!(f, "put_structure {}/{}, A{}", name, arity, r.reg_num()),
            &QueryInstruction::PutUnsafeValue(y, a) =>
                write!(f, "put_unsafe_value Y{}, A{}", y, a),
            &QueryInstruction::PutValue(ref x, ref a) =>
                write!(f, "put_value {}, A{}", x, a),
            &QueryInstruction::PutVariable(ref x, ref a) =>
                write!(f, "put_variable {}, A{}", x, a),
            &QueryInstruction::SetConstant(ref constant) =>
                write!(f, "set_constant {}", constant),
            &QueryInstruction::SetLocalValue(ref r) =>
                write!(f, "set_local_value {}", r),
            &QueryInstruction::SetVariable(ref r) =>
                write!(f, "set_variable {}", r),
            &QueryInstruction::SetValue(ref r) =>
                write!(f, "set_value {}", r),
            &QueryInstruction::SetVoid(n) =>
                write!(f, "set_void {}", n)
        }
    }
}

impl fmt::Display for ControlInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ControlInstruction::Allocate(num_cells) =>
                write!(f, "allocate {}", num_cells),
            &ControlInstruction::Call(ref name, arity, pvs) =>
                write!(f, "call {}/{}, {}", name, arity, pvs),
            &ControlInstruction::CallN(arity) =>
                write!(f, "call_N {}", arity),
            &ControlInstruction::Catch =>
                write!(f, "catch"),
            &ControlInstruction::ExecuteN(arity) =>
                write!(f, "execute_N {}", arity),
            &ControlInstruction::Deallocate =>
                write!(f, "deallocate"),
            &ControlInstruction::Execute(ref name, arity) =>
                write!(f, "execute {}/{}", name, arity),
            &ControlInstruction::Proceed =>
                write!(f, "proceed"),
            &ControlInstruction::Throw =>
                write!(f, "throw")
        }
    }
}

impl fmt::Display for IndexedChoiceInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &IndexedChoiceInstruction::Try(offset) =>
                write!(f, "try {}", offset),
            &IndexedChoiceInstruction::Retry(offset) =>
                write!(f, "retry {}", offset),
            &IndexedChoiceInstruction::Trust(offset) =>
                write!(f, "trust {}", offset)
        }
    }
}

impl fmt::Display for ChoiceInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ChoiceInstruction::TryMeElse(offset) =>
                write!(f, "try_me_else {}", offset),
            &ChoiceInstruction::RetryMeElse(offset) =>
                write!(f, "retry_me_else {}", offset),
            &ChoiceInstruction::TrustMe =>
                write!(f, "trust_me")
        }
    }
}

impl fmt::Display for IndexingInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &IndexingInstruction::SwitchOnTerm(v, c, l, s) =>
                write!(f, "switch_on_term {}, {}, {}, {}", v, c, l, s),
            &IndexingInstruction::SwitchOnConstant(num_cs, _) =>
                write!(f, "switch_on_constant {}", num_cs),
            &IndexingInstruction::SwitchOnStructure(num_ss, _) =>
                write!(f, "switch_on_structure {}", num_ss)
        }
    }
}

impl fmt::Display for CutInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &CutInstruction::Cut(_) =>
                write!(f, "cut"),
            &CutInstruction::NeckCut(_) =>
                write!(f, "neck_cut"),
            &CutInstruction::GetLevel =>
                write!(f, "get_level")
        }
    }
}

impl fmt::Display for Level {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Level::Shallow => write!(f, "A"),
            &Level::Deep => write!(f, "X")
        }
    }
}

impl fmt::Display for VarReg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg),
            &VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg),
            &VarReg::ArgAndNorm(RegType::Perm(reg), arg) =>
                write!(f, "Y{} A{}", reg, arg),
            &VarReg::ArgAndNorm(RegType::Temp(reg), arg) =>
                write!(f, "X{} A{}", reg, arg)
        }
    }
}

impl fmt::Display for RegType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &RegType::Perm(val) => write!(f, "Y{}", val),
            &RegType::Temp(val) => write!(f, "X{}", val)
        }
    }
}

/*
// Wait until constexprs are supported in stable before trying to
// switch to this.

struct ClauseRewriter { field: fn(&mut Vec<Box<Term>>) -> QueryTerm }

impl Clone for ClauseRewriter {
    fn clone(&self) -> Self {
        ClauseRewriter { field: self.field }
    }
}

struct ClauseRewriters {
    rewriter_map: HashMap<&'static str, ClauseRewriter>
}

impl ClauseRewriters {
    fn new() -> Self {
        let mut rewriter_map =
            [("call", ClauseRewriter { field: rewrite_call_N })]//,
        //("catch", rewrite_catch),
        //("throw", rewrite_throw)]
            .iter().cloned().collect();

        ClauseRewriters { rewriter_map: rewriter_map }
    }

    fn get(&self, name: &str) -> Option<&ClauseRewriter> {
        self.rewriter_map.get(name)
    }
}
*/

fn rewrite_call_n(terms: &mut Vec<Box<Term>>) -> QueryTerm {
    let mut new_terms = Vec::with_capacity(0);
    swap(&mut new_terms, terms);

    QueryTerm::CallN(new_terms)
}

fn rewrite_catch(terms: &mut Vec<Box<Term>>) -> QueryTerm {
    let mut new_terms = Vec::with_capacity(0);
    swap(&mut new_terms, terms);

    QueryTerm::Catch(new_terms)
}

fn rewrite_throw(terms: &mut Vec<Box<Term>>) -> QueryTerm {
    let mut new_terms = Vec::with_capacity(0);
    swap(&mut new_terms, terms);

    QueryTerm::Throw(new_terms)
}

fn rewrite_clause(name: &Atom, terms: &mut Vec<Box<Term>>) -> Option<QueryTerm>
{
    if name == "call" {
        Some(rewrite_call_n(terms))
    } else if name == "catch" && terms.len() == 3 {
        Some(rewrite_catch(terms))
    } else if name == "throw" && terms.len() == 1 {
        Some(rewrite_throw(terms))
    } else {
        None
    }
}

pub fn parse_code(input: &str) -> Option<TopLevel>
{
    match parse_TopLevel(input) {
        Ok(mut tl) => {
            for query in tl.query_iter_mut() {
                let new_query = match query {
                    &mut QueryTerm::Term(Term::Clause(_, ref name, ref mut cts)) =>
                        rewrite_clause(name, cts),
                    &mut QueryTerm::Term(Term::Var(_, _)) =>
                        Some(QueryTerm::CallN(Vec::new())),
                    _ => None
                };

                if let Some(mut new_query) = new_query {
                    swap(&mut new_query, query);
                }
            }

            Some(tl)
        },
        Err(_) => None
    }
}

fn is_consistent(predicate: &Vec<PredicateClause>) -> bool {
    let name  = predicate.first().unwrap().name();
    let arity = predicate.first().unwrap().arity();

    for clause in predicate.iter().skip(1) {
        if !(name == clause.name() && arity == clause.arity()) {
            return false;
        }
    }

    true
}

#[allow(dead_code)]
pub fn print_code(code: &Code) {
    for clause in code {
        match clause {
            &Line::Fact(ref fact) =>
                for fact_instr in fact {
                    println!("{}", fact_instr);
                },
            &Line::BuiltIn(_) => {},
            &Line::Cut(ref cut) =>
                println!("{}", cut),
            &Line::Choice(ref choice) =>
                println!("{}", choice),
            &Line::Control(ref control) =>
                println!("{}", control),
            &Line::IndexedChoice(ref choice) =>
                println!("{}", choice),
            &Line::Indexing(ref indexing) =>
                println!("{}", indexing),
            &Line::Query(ref query) =>
                for query_instr in query {
                    println!("{}", query_instr);
                }
        }
    }
}

pub fn read() -> String {
    let _ = stdout().flush();

    let mut buffer = String::new();
    let mut result = String::new();

    let stdin = stdin();
    stdin.read_line(&mut buffer).unwrap();

    if &*buffer.trim() == ":{" {
        buffer.clear();

        stdin.read_line(&mut buffer).unwrap();

        while &*buffer.trim() != "}:" {
            result += buffer.as_str();
            buffer.clear();
            stdin.read_line(&mut buffer).unwrap();
        }
    } else {
        result = buffer;
    }

    result
}

pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'b>
{
    match tl {
        &TopLevel::Predicate(ref clauses) => {
            let mut cg = CodeGenerator::<DebrayAllocator>::new();

            if is_consistent(clauses) {
                let compiled_pred = cg.compile_predicate(clauses);
                wam.add_predicate(clauses, compiled_pred)
            } else {
                let msg = r"Error: predicate is inconsistent.
Each predicate must have the same name and arity.";

                EvalSession::EntryFailure(String::from(msg))
            }
        },
        &TopLevel::Fact(ref fact) => {
            let mut cg = CodeGenerator::<DebrayAllocator>::new();

            let compiled_fact = cg.compile_fact(fact);
            wam.add_fact(fact, compiled_fact)
        },
        &TopLevel::Rule(ref rule) => {
            let mut cg = CodeGenerator::<DebrayAllocator>::new();

            let compiled_rule = cg.compile_rule(rule);
            wam.add_rule(rule, compiled_rule)
        },
        &TopLevel::Query(ref query) => {
            let mut cg = CodeGenerator::<DebrayAllocator>::new();

            let compiled_query = cg.compile_query(query);
            print_code(&compiled_query);
            wam.submit_query(compiled_query, cg.take_vars())
        }
    }
}

pub fn print(wam: &mut Machine, result: EvalSession) {
    match result {
        EvalSession::InitialQuerySuccess(alloc_locs, mut heap_locs) => {
            print!("true");

            if !wam.or_stack_is_empty() {
                print!(" ");
            }

            println!(".");

            if heap_locs.is_empty() {
                return;
            }

            loop {
                let mut result = EvalSession::QueryFailure;
                let bindings = wam.heap_view(&heap_locs);

                let stdin  = stdin();
                let mut stdout = stdout().into_raw_mode().unwrap();

                write!(stdout, "{}", bindings).unwrap();
                stdout.flush().unwrap();

                if !wam.or_stack_is_empty() {
                    stdout.flush().unwrap();

                    for c in stdin.keys() {
                        match c.unwrap() {
                            Key::Char(';') => {
                                write!(stdout, " ;\n\r").unwrap();
                                result = wam.continue_query(&alloc_locs, &mut heap_locs);
                                break;
                            },
                            Key::Char('.') => {
                                write!(stdout, " .\n\r").unwrap();
                                return;
                            },
                            _ => {}
                        }
                    }

                    if let &EvalSession::QueryFailure = &result {
                        write!(stdout, "false.\n\r").unwrap();
                        stdout.flush().unwrap();
                        return;
                    }
                } else {
                    break;
                }
            }

            write!(stdout(), ".\n").unwrap();
        },
        EvalSession::QueryFailure => println!("false."),
        EvalSession::EntryFailure(msg) => println!("{}", msg),
        _ => {}
    };
}
<commit_msg>remove diagnostic message<commit_after>use prolog::ast::*;
use prolog::codegen::*;
use prolog::debray_allocator::*;
use prolog::machine::*;
use prolog::prolog_parser::*;

use termion::raw::IntoRawMode;
use termion::input::TermRead;
use termion::event::Key;

use std::io::{Write, stdin, stdout};
use std::fmt;
use std::mem::swap;

impl fmt::Display for Constant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Constant::Atom(ref atom) =>
                write!(f, "{}", atom),
            &Constant::EmptyList =>
                write!(f, "[]"),
            &Constant::UInt64(integer) =>
                write!(f, "u{}", integer)
        }
    }
}

impl fmt::Display for FactInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &FactInstruction::GetConstant(Level::Shallow, ref constant, ref r) =>
                write!(f, "get_constant {}, A{}", constant, r.reg_num()),
            &FactInstruction::GetConstant(Level::Deep, ref constant, ref r) =>
                write!(f, "get_constant {}, {}", constant, r),
            &FactInstruction::GetList(Level::Shallow, ref r) =>
                write!(f, "get_list A{}", r.reg_num()),
            &FactInstruction::GetList(Level::Deep, ref r) =>
                write!(f, "get_list {}", r),
            &FactInstruction::GetStructure(Level::Deep, ref name, ref arity, ref r) =>
                write!(f, "get_structure {}/{}, {}", name, arity, r),
            &FactInstruction::GetStructure(Level::Shallow, ref name, ref arity, ref r) =>
                write!(f, "get_structure {}/{}, A{}", name, arity, r.reg_num()),
            &FactInstruction::GetValue(ref x, ref a) =>
                write!(f, "get_value {}, A{}", x, a),
            &FactInstruction::GetVariable(ref x, ref a) =>
                write!(f, "get_variable {}, A{}", x, a),
            &FactInstruction::UnifyConstant(ref constant) =>
                write!(f, "unify_constant {}", constant),
            &FactInstruction::UnifyVariable(ref r) =>
                write!(f, "unify_variable {}", r),
            &FactInstruction::UnifyLocalValue(ref r) =>
                write!(f, "unify_local_value {}", r),
            &FactInstruction::UnifyValue(ref r) =>
                write!(f, "unify_value {}", r),
            &FactInstruction::UnifyVoid(n) =>
                write!(f, "unify_void {}", n)
        }
    }
}

impl fmt::Display for QueryInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &QueryInstruction::GetVariable(ref x, ref a) =>
                write!(f, "get_variable {}, A{}", x, a),
            &QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
                write!(f, "put_constant {}, A{}", constant, r.reg_num()),
            &QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) =>
                write!(f, "put_constant {}, {}", constant, r),
            &QueryInstruction::PutList(Level::Shallow, ref r) =>
                write!(f, "put_list A{}", r.reg_num()),
            &QueryInstruction::PutList(Level::Deep, ref r) =>
                write!(f, "put_list {}", r),
            &QueryInstruction::PutStructure(Level::Deep, ref name, ref arity, ref r) =>
                write!(f, "put_structure {}/{}, {}", name, arity, r),
            &QueryInstruction::PutStructure(Level::Shallow, ref name, ref arity, ref r) =>
                write!(f, "put_structure {}/{}, A{}", name, arity, r.reg_num()),
            &QueryInstruction::PutUnsafeValue(y, a) =>
                write!(f, "put_unsafe_value Y{}, A{}", y, a),
            &QueryInstruction::PutValue(ref x, ref a) =>
                write!(f, "put_value {}, A{}", x, a),
            &QueryInstruction::PutVariable(ref x, ref a) =>
                write!(f, "put_variable {}, A{}", x, a),
            &QueryInstruction::SetConstant(ref constant) =>
                write!(f, "set_constant {}", constant),
            &QueryInstruction::SetLocalValue(ref r) =>
                write!(f, "set_local_value {}", r),
            &QueryInstruction::SetVariable(ref r) =>
                write!(f, "set_variable {}", r),
            &QueryInstruction::SetValue(ref r) =>
                write!(f, "set_value {}", r),
            &QueryInstruction::SetVoid(n) =>
                write!(f, "set_void {}", n)
        }
    }
}

impl fmt::Display for ControlInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ControlInstruction::Allocate(num_cells) =>
                write!(f, "allocate {}", num_cells),
            &ControlInstruction::Call(ref name, arity, pvs) =>
                write!(f, "call {}/{}, {}", name, arity, pvs),
            &ControlInstruction::CallN(arity) =>
                write!(f, "call_N {}", arity),
            &ControlInstruction::Catch =>
                write!(f, "catch"),
            &ControlInstruction::ExecuteN(arity) =>
                write!(f, "execute_N {}", arity),
            &ControlInstruction::Deallocate =>
                write!(f, "deallocate"),
            &ControlInstruction::Execute(ref name, arity) =>
                write!(f, "execute {}/{}", name, arity),
            &ControlInstruction::Proceed =>
                write!(f, "proceed"),
            &ControlInstruction::Throw =>
                write!(f, "throw")
        }
    }
}

impl fmt::Display for IndexedChoiceInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &IndexedChoiceInstruction::Try(offset) =>
                write!(f, "try {}", offset),
            &IndexedChoiceInstruction::Retry(offset) =>
                write!(f, "retry {}", offset),
            &IndexedChoiceInstruction::Trust(offset) =>
                write!(f, "trust {}", offset)
        }
    }
}

impl fmt::Display for ChoiceInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ChoiceInstruction::TryMeElse(offset) =>
                write!(f, "try_me_else {}", offset),
            &ChoiceInstruction::RetryMeElse(offset) =>
                write!(f, "retry_me_else {}", offset),
            &ChoiceInstruction::TrustMe =>
                write!(f, "trust_me")
        }
    }
}

impl fmt::Display for IndexingInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &IndexingInstruction::SwitchOnTerm(v, c, l, s) =>
                write!(f, "switch_on_term {}, {}, {}, {}", v, c, l, s),
            &IndexingInstruction::SwitchOnConstant(num_cs, _) =>
                write!(f, "switch_on_constant {}", num_cs),
            &IndexingInstruction::SwitchOnStructure(num_ss, _) =>
                write!(f, "switch_on_structure {}", num_ss)
        }
    }
}

impl fmt::Display for CutInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &CutInstruction::Cut(_) =>
                write!(f, "cut"),
            &CutInstruction::NeckCut(_) =>
                write!(f, "neck_cut"),
            &CutInstruction::GetLevel =>
                write!(f, "get_level")
        }
    }
}

impl fmt::Display for Level {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Level::Shallow => write!(f, "A"),
            &Level::Deep => write!(f, "X")
        }
    }
}

impl fmt::Display for VarReg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg),
            &VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg),
            &VarReg::ArgAndNorm(RegType::Perm(reg), arg) =>
                write!(f, "Y{} A{}", reg, arg),
            &VarReg::ArgAndNorm(RegType::Temp(reg), arg) =>
                write!(f, "X{} A{}", reg, arg)
        }
    }
}

impl fmt::Display for RegType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &RegType::Perm(val) => write!(f, "Y{}", val),
            &RegType::Temp(val) => write!(f, "X{}", val)
        }
    }
}

/*
// Wait until constexprs are supported in stable before trying to
// switch to this.

struct ClauseRewriter { field: fn(&mut Vec<Box<Term>>) -> QueryTerm }

impl Clone for ClauseRewriter {
    fn clone(&self) -> Self {
        ClauseRewriter { field: self.field }
    }
}

struct ClauseRewriters {
    rewriter_map: HashMap<&'static str, ClauseRewriter>
}

impl ClauseRewriters {
    fn new() -> Self {
        let mut rewriter_map =
            [("call", ClauseRewriter { field: rewrite_call_N })]//,
        //("catch", rewrite_catch),
        //("throw", rewrite_throw)]
            .iter().cloned().collect();

        ClauseRewriters { rewriter_map: rewriter_map }
    }

    fn get(&self, name: &str) -> Option<&ClauseRewriter> {
        self.rewriter_map.get(name)
    }
}
*/

fn rewrite_call_n(terms: &mut Vec<Box<Term>>) -> QueryTerm {
    let mut new_terms = Vec::with_capacity(0);
    swap(&mut new_terms, terms);

    QueryTerm::CallN(new_terms)
}

fn rewrite_catch(terms: &mut Vec<Box<Term>>) -> QueryTerm {
    let mut new_terms = Vec::with_capacity(0);
    swap(&mut new_terms, terms);

    QueryTerm::Catch(new_terms)
}

fn rewrite_throw(terms: &mut Vec<Box<Term>>) -> QueryTerm {
    let mut new_terms = Vec::with_capacity(0);
    swap(&mut new_terms, terms);

    QueryTerm::Throw(new_terms)
}

fn rewrite_clause(name: &Atom, terms: &mut Vec<Box<Term>>) -> Option<QueryTerm>
{
    if name == "call" {
        Some(rewrite_call_n(terms))
    } else if name == "catch" && terms.len() == 3 {
        Some(rewrite_catch(terms))
    } else if name == "throw" && terms.len() == 1 {
        Some(rewrite_throw(terms))
    } else {
        None
    }
}

pub fn parse_code(input: &str) -> Option<TopLevel>
{
    match parse_TopLevel(input) {
        Ok(mut tl) => {
            for query in tl.query_iter_mut() {
                let new_query = match query {
                    &mut QueryTerm::Term(Term::Clause(_, ref name, ref mut cts)) =>
                        rewrite_clause(name, cts),
                    &mut QueryTerm::Term(Term::Var(_, _)) =>
                        Some(QueryTerm::CallN(Vec::new())),
                    _ => None
                };

                if let Some(mut new_query) = new_query {
                    swap(&mut new_query, query);
                }
            }

            Some(tl)
        },
        Err(_) => None
    }
}

fn is_consistent(predicate: &Vec<PredicateClause>) -> bool {
    let name  = predicate.first().unwrap().name();
    let arity = predicate.first().unwrap().arity();

    for clause in predicate.iter().skip(1) {
        if !(name == clause.name() && arity == clause.arity()) {
            return false;
        }
    }

    true
}

#[allow(dead_code)]
pub fn print_code(code: &Code) {
    for clause in code {
        match clause {
            &Line::Fact(ref fact) =>
                for fact_instr in fact {
                    println!("{}", fact_instr);
                },
            &Line::BuiltIn(_) => {},
            &Line::Cut(ref cut) =>
                println!("{}", cut),
            &Line::Choice(ref choice) =>
                println!("{}", choice),
            &Line::Control(ref control) =>
                println!("{}", control),
            &Line::IndexedChoice(ref choice) =>
                println!("{}", choice),
            &Line::Indexing(ref indexing) =>
                println!("{}", indexing),
            &Line::Query(ref query) =>
                for query_instr in query {
                    println!("{}", query_instr);
                }
        }
    }
}

pub fn read() -> String {
    let _ = stdout().flush();

    let mut buffer = String::new();
    let mut result = String::new();

    let stdin = stdin();
    stdin.read_line(&mut buffer).unwrap();

    if &*buffer.trim() == ":{" {
        buffer.clear();

        stdin.read_line(&mut buffer).unwrap();

        while &*buffer.trim() != "}:" {
            result += buffer.as_str();
            buffer.clear();
            stdin.read_line(&mut buffer).unwrap();
        }
    } else {
        result = buffer;
    }

    result
}

pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'b>
{
    match tl {
        &TopLevel::Predicate(ref clauses) => {
            let mut cg = CodeGenerator::<DebrayAllocator>::new();

            if is_consistent(clauses) {
                let compiled_pred = cg.compile_predicate(clauses);
                wam.add_predicate(clauses, compiled_pred)
            } else {
                let msg = r"Error: predicate is inconsistent.
Each predicate must have the same name and arity.";

                EvalSession::EntryFailure(String::from(msg))
            }
        },
        &TopLevel::Fact(ref fact) => {
            let mut cg = CodeGenerator::<DebrayAllocator>::new();

            let compiled_fact = cg.compile_fact(fact);
            wam.add_fact(fact, compiled_fact)
        },
        &TopLevel::Rule(ref rule) => {
            let mut cg = CodeGenerator::<DebrayAllocator>::new();

            let compiled_rule = cg.compile_rule(rule);
            wam.add_rule(rule, compiled_rule)
        },
        &TopLevel::Query(ref query) => {
            let mut cg = CodeGenerator::<DebrayAllocator>::new();

            let compiled_query = cg.compile_query(query);
            wam.submit_query(compiled_query, cg.take_vars())
        }
    }
}

pub fn print(wam: &mut Machine, result: EvalSession) {
    match result {
        EvalSession::InitialQuerySuccess(alloc_locs, mut heap_locs) => {
            print!("true");

            if !wam.or_stack_is_empty() {
                print!(" ");
            }

            println!(".");

            if heap_locs.is_empty() {
                return;
            }

            loop {
                let mut result = EvalSession::QueryFailure;
                let bindings = wam.heap_view(&heap_locs);

                let stdin  = stdin();
                let mut stdout = stdout().into_raw_mode().unwrap();

                write!(stdout, "{}", bindings).unwrap();
                stdout.flush().unwrap();

                if !wam.or_stack_is_empty() {
                    stdout.flush().unwrap();

                    for c in stdin.keys() {
                        match c.unwrap() {
                            Key::Char(';') => {
                                write!(stdout, " ;\n\r").unwrap();
                                result = wam.continue_query(&alloc_locs, &mut heap_locs);
                                break;
                            },
                            Key::Char('.') => {
                                write!(stdout, " .\n\r").unwrap();
                                return;
                            },
                            _ => {}
                        }
                    }

                    if let &EvalSession::QueryFailure = &result {
                        write!(stdout, "false.\n\r").unwrap();
                        stdout.flush().unwrap();
                        return;
                    }
                } else {
                    break;
                }
            }

            write!(stdout(), ".\n").unwrap();
        },
        EvalSession::QueryFailure => println!("false."),
        EvalSession::EntryFailure(msg) => println!("{}", msg),
        _ => {}
    };
}
<|endoftext|>