<commit_before>/// Representation of a mathematical vector e.g. a position or velocity
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Vector2<T>(pub T, pub T);

use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, Div, Neg};
use std::convert::From;

/// Special methods for floating point vectors
pub trait FloatVector<F>{
    /// Creates a new unit vector in a specific direction
    fn unit_vector(F) -> Self;
    /// Normalises the vector
    fn normalise(self) -> Self;
    /// Returns the magnitude or the length of the vector
    fn length(&self) -> F;
    /// Returns direction the vector is pointing
    fn direction(&self) -> F;
    /// Returns direction towards another vector
    fn direction_to(&self, &Self) -> F;
    /// Returns the distance betweens two vectors
    fn distance_to(&self, &Self) -> F;
}

macro_rules! impl_for {
    ($($t:ty)*) => {$(
        impl FloatVector<$t> for Vector2<$t>{
            fn unit_vector(direction: $t) -> Self{
                let (y, x) = direction.sin_cos();
                Vector2(x, y)
            }

            fn normalise(self) -> Self{
                let length = self.length();
                self / length
            }

            fn length(&self) -> $t{
                self.0.hypot(self.1)
            }

            fn direction(&self) -> $t{
                (-self.1).atan2(self.0)
            }

            fn direction_to(&self, other: &Self) -> $t{
                (*other-*self).direction()
            }

            fn distance_to(&self, other: &Self) -> $t{
                (self.0 - other.0).hypot(self.1 - other.1)
            }
        }

        impl Mul<Vector2<$t>> for $t{
            type Output = Vector2<$t>;

            fn mul(self, rhs: Vector2<$t>) -> Vector2<$t>{
                Vector2(self * rhs.0, self * rhs.1)
            }
        }

        impl Div<Vector2<$t>> for $t{
            type Output = Vector2<$t>;

            fn div(self, rhs: Vector2<$t>) -> Vector2<$t>{
                Vector2(self / rhs.0, self / rhs.1)
            }
        }
    )*};
}

impl_for!(f32 f64);

impl<T> Vector2<T> {
    /// Returns the dot product of two vectors
    pub fn dot(self, other: Self) -> T where T: Mul<Output=T> + Add<Output=T>{
        self.0 * other.0 + self.1 * other.1
    }
    /// Returns the fields in a tuple
    pub fn to_tuple(self) -> (T, T){
        (self.0, self.1)
    }
    /// Returns an array of the two fields
    pub fn to_array(self) -> [T; 2]{
        [self.0, self.1]
    }
}

impl<T: Add<Output=T>> Add for Vector2<T>{
    type Output = Self;

    fn add(self, rhs: Self) -> Self{
        Vector2(self.0 + rhs.0, self.1 + rhs.1)
    }
}

impl<T: Sub<Output=T>> Sub for Vector2<T>{
    type Output = Self;

    fn sub(self, rhs: Self) -> Self{
        Vector2(self.0 - rhs.0, self.1 - rhs.1)
    }
}

impl<T: Add<Output=T> + Copy> AddAssign for Vector2<T>{
    fn add_assign(&mut self, rhs: Self){
        *self = *self + rhs
    }
}

impl<T: Sub<Output=T> + Copy> SubAssign for Vector2<T>{
    fn sub_assign(&mut self, rhs: Self){
        *self = *self - rhs
    }
}

impl<T: Mul<Output=T> + Copy> Mul<T> for Vector2<T>{
    type Output = Self;

    fn mul(self, rhs: T) -> Self{
        Vector2(self.0 * rhs, self.1 * rhs)
    }
}

impl<T: Div<Output=T> + Copy> Div<T> for Vector2<T>{
    type Output = Self;

    fn div(self, rhs: T) -> Self{
        Vector2(self.0/rhs, self.1/rhs)
    }
}

impl<T: Neg<Output=T>> Neg for Vector2<T>{
    type Output = Self;

    fn neg(self) -> Self{
        Vector2(-self.0, -self.1)
    }
}

impl<T> Into<(T, T)> for Vector2<T>{
    #[inline(always)]
    fn into(self) -> (T, T){
        self.to_tuple()
    }
}

impl<T> From<(T, T)> for Vector2<T>{
    #[inline(always)]
    fn from(tuple: (T, T)) -> Self{
        Vector2(tuple.0, tuple.1)
    }
}
<commit_msg>Make *Assign impls for Vector2 not require Copy<commit_after>/// Representation of a mathematical vector e.g. a position or velocity
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Vector2<T>(pub T, pub T);

use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, Div, Neg};
use std::convert::From;

/// Special methods for floating point vectors
pub trait FloatVector<F>{
    /// Creates a new unit vector in a specific direction
    fn unit_vector(F) -> Self;
    /// Normalises the vector
    fn normalise(self) -> Self;
    /// Returns the magnitude or the length of the vector
    fn length(&self) -> F;
    /// Returns direction the vector is pointing
    fn direction(&self) -> F;
    /// Returns direction towards another vector
    fn direction_to(&self, &Self) -> F;
    /// Returns the distance betweens two vectors
    fn distance_to(&self, &Self) -> F;
}

macro_rules! impl_for {
    ($($t:ty)*) => {$(
        impl FloatVector<$t> for Vector2<$t>{
            fn unit_vector(direction: $t) -> Self{
                let (y, x) = direction.sin_cos();
                Vector2(x, y)
            }

            fn normalise(self) -> Self{
                let length = self.length();
                self / length
            }

            fn length(&self) -> $t{
                self.0.hypot(self.1)
            }

            fn direction(&self) -> $t{
                (-self.1).atan2(self.0)
            }

            fn direction_to(&self, other: &Self) -> $t{
                (*other-*self).direction()
            }

            fn distance_to(&self, other: &Self) -> $t{
                (self.0 - other.0).hypot(self.1 - other.1)
            }
        }

        impl Mul<Vector2<$t>> for $t{
            type Output = Vector2<$t>;

            fn mul(self, rhs: Vector2<$t>) -> Vector2<$t>{
                Vector2(self * rhs.0, self * rhs.1)
            }
        }

        impl Div<Vector2<$t>> for $t{
            type Output = Vector2<$t>;

            fn div(self, rhs: Vector2<$t>) -> Vector2<$t>{
                Vector2(self / rhs.0, self / rhs.1)
            }
        }
    )*};
}

impl_for!(f32 f64);

impl<T> Vector2<T> {
    /// Returns the dot product of two vectors
    pub fn dot(self, other: Self) -> T where T: Mul<Output=T> + Add<Output=T>{
        self.0 * other.0 + self.1 * other.1
    }
    /// Returns the fields in a tuple
    pub fn to_tuple(self) -> (T, T){
        (self.0, self.1)
    }
    /// Returns an array of the two fields
    pub fn to_array(self) -> [T; 2]{
        [self.0, self.1]
    }
}

impl<T: Add<Output=T>> Add for Vector2<T>{
    type Output = Self;

    fn add(self, rhs: Self) -> Self{
        Vector2(self.0 + rhs.0, self.1 + rhs.1)
    }
}

impl<T: Sub<Output=T>> Sub for Vector2<T>{
    type Output = Self;

    fn sub(self, rhs: Self) -> Self{
        Vector2(self.0 - rhs.0, self.1 - rhs.1)
    }
}

impl<T: AddAssign> AddAssign for Vector2<T>{
    fn add_assign(&mut self, rhs: Self){
        self.0 += rhs.0;
        self.1 += rhs.1;
    }
}

impl<T: SubAssign> SubAssign for Vector2<T>{
    fn sub_assign(&mut self, rhs: Self){
        self.0 -= rhs.0;
        self.1 -= rhs.1;
    }
}

impl<T: Mul<Output=T> + Copy> Mul<T> for Vector2<T>{
    type Output = Self;

    fn mul(self, rhs: T) -> Self{
        Vector2(self.0 * rhs, self.1 * rhs)
    }
}

impl<T: Div<Output=T> + Copy> Div<T> for Vector2<T>{
    type Output = Self;

    fn div(self, rhs: T) -> Self{
        Vector2(self.0/rhs, self.1/rhs)
    }
}

impl<T: Neg<Output=T>> Neg for Vector2<T>{
    type Output = Self;

    fn neg(self) -> Self{
        Vector2(-self.0, -self.1)
    }
}

impl<T> Into<(T, T)> for Vector2<T>{
    #[inline(always)]
    fn into(self) -> (T, T){
        self.to_tuple()
    }
}

impl<T> From<(T, T)> for Vector2<T>{
    #[inline(always)]
    fn from(tuple: (T, T)) -> Self{
        Vector2(tuple.0, tuple.1)
    }
}
<|endoftext|>


<commit_before>use common::*;
use env_logger;
use std::fmt;
use std::io::{Read, Write};
use std::num::Wrapping;

mod events;
mod memory;
mod modes;
mod opcodes;
mod registers;

use self::events::*;
use self::memory::*;
use self::modes::*;
use self::opcodes::*;
use self::registers::*;

include!("tests.rs");

pub struct VM<R: Read, W: Write> {
    input: R,
    output: W,

    registers: Registers,
    memory: Memory,
    terminated: bool,
}

impl<R: Read, W: Write> VM<R, W> {
    pub fn new(input: R, output: W, executable: Data) -> Self {
        let memory = Memory::from_executable(executable);

        VM {
            input: input,
            output: output,
            registers: [0; REGISTERS as usize],
            memory: memory,
            terminated: false,
        }
    }

    pub fn run(&mut self) {
        self.set_register(PC, CODE_OFFSET as Word);

        let stack_end = self.memory.stack_end;
        self.set_register(SP, stack_end);

        let event_queue_end = self.memory.event_queue_end;
        self.set_register(EP, event_queue_end);
        self.set_register(EE, event_queue_end);

        let mut args = vec![];
        while !self.terminated {
            let pc = self.get_register(PC);
            if !self.memory.is_in_code(pc) && self.event_queue().is_empty() {
                self.terminate();
            } else {
                self.fetch()
                    .decode(&mut args)
                    .execute(&args)
                    .process_events();
                args.clear();
            }
        }

        self.output.flush().unwrap();
    }

    pub fn code(&self) -> DataSlice {
        self.memory.code()
    }

    pub fn data(&self) -> DataSlice {
        self.memory.data()
    }

    pub fn stack(&self) -> DataSlice {
        let sp = self.get_register(SP);
        self.memory.stack(sp)
    }

    pub fn event_queue(&self) -> DataSlice {
        let ep = self.get_register(EP);
        let ee = self.get_register(EE);
        self.memory.event_queue(ep, ee)
    }

    fn terminate(&mut self) {
        debug!("terminate {:?}", self);
        self.terminated = true;
    }

    fn fetch(&mut self) -> &mut Self {
        debug!("fetch {:?}", self);

        let opcode = self.next_code_byte() as Word;
        self.set_register(IR, opcode);
        self
    }

    fn decode(&mut self, args: &mut Data) -> &mut Self {
        debug!("decode {:?}", self);

        let opcode = self.get_register(IR) as u8;
        match opcode {
            ADD | SUB | MUL | DIV | MOD | SWP => {
                if self.stack().len() >= 2 {
                    args.push(self.stack_pop());
                    args.push(self.stack_pop());
                }
            }
            INC | DEC => {
                if !self.stack().is_empty() {
                    args.push(self.stack_pop());
                }
            }
            PUSH => args.push(self.next_code_byte()),
            POP | NOP => (),
            LOAD | STORE => {
                args.push(self.next_code_byte());
                args.push(self.next_code_byte());
                args.push(self.next_code_byte());
            }
            EMIT => {
                let event = self.next_code_byte();
                let argument = if self.stack().is_empty() {
                    0x00
                } else {
                    self.stack_top()
                };
                args.push(event);
                args.push(argument);
            }
            _ => unimplemented!(),
        }

        self
    }

    fn execute(&mut self, args: DataSlice) -> &mut Self {
        debug!("execute {:?}", self);

        let opcode = self.get_register(IR) as u8;
        match opcode {
            NOP => (),
            ADD => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let value = Wrapping(args[0]) + Wrapping(args[1]);
                    self.stack_push(value.0);
                }
            }
            SUB => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let value = Wrapping(args[0]) - Wrapping(args[1]);
                    self.stack_push(value.0);
                }
            }
            MUL => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let value = Wrapping(args[0]) * Wrapping(args[1]);
                    self.stack_push(value.0);
                }
            }
            DIV => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else if args[1] == 0 {
                    self.process_event(UNKNOWN_ERROR, 0x00);
                } else {
                    let value = Wrapping(args[0]) / Wrapping(args[1]);
                    self.stack_push(value.0);
                }
            }
            MOD => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else if args[1] == 0 {
                    self.process_event(UNKNOWN_ERROR, 0x00);
                } else {
                    let value = Wrapping(args[0]) % Wrapping(args[1]);
                    self.stack_push(value.0);
                }
            }
            INC => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let value = Wrapping(args[0]) + Wrapping(1);
                    self.stack_push(value.0);
                }
            }
            DEC => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let value = Wrapping(args[0]) - Wrapping(1);
                    self.stack_push(value.0);
                }
            }
            PUSH => {
                if self.get_register(SP) <= self.memory.stack_begin {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    self.stack_push(args[0]);
                }
            }
            POP => {
                if self.stack().is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let _ = self.stack_pop();
                }
            }
            SWP => {
                if args.len() < 2 {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    self.stack_push(args[0]);
                    self.stack_push(args[1]);
                }
            }
            LOAD => {
                match self.load_data(args) {
                    Some(byte) => self.stack_push(byte),
                    None => self.process_event(SEGFAULT, 0x00),
                }
            }
            STORE => {
                unimplemented!();
            }
            EMIT => {
                let event = args[0];
                let argument = args[1];
                if events::is_critical(event) {
                    self.process_event(event, argument);
                } else {
                    self.event_queue_push(event, argument);
                }
            }
            _ => unimplemented!(),
        }

        self
    }

    fn load_data(&self, args: DataSlice) -> Option<u8> {
        self.extract_data_ptr(args)
            .map(|ptr| self.memory.get(ptr))
    }

    fn extract_data_ptr(&self, args: DataSlice) -> Option<Word> {
        self.extract_ptr(args)
            .and_then(|ptr| if self.memory.is_in_data(ptr) {
                Some(ptr)
            } else {
                None
            })
    }

    fn extract_ptr(&self, args: DataSlice) -> Option<Word> {
        let mode = args[0];
        let ptr = Memory::read_word_from(&args, 1);

        let updated_ptr = match mode {
            PTR => ptr,
            PTR_WITH_OFFSET => {
                if self.stack().is_empty() {
                    return None;
                } else {
                    let offset = self.stack_top() as Word;
                    ptr + offset
                }
            }
            _ => unreachable!(),
        };

        Some(updated_ptr)
    }

    fn process_event(&mut self, event: u8, argument: u8) {
        debug!("process_event event={} argument={}",
               to_hex!(event),
               to_hex!(argument));

        let handler = self.memory.get_event_handler(event);
        if handler == 0 {
            debug!("handler is NOT set");
            match event {
                INPUT => {
                    let mut buffer = [0; 1];
                    let _ = self.input.read(&mut buffer).unwrap();
                    self.stack_push(buffer[0]);
                }
                OUTPUT => {
                    self.output.write(&[argument]).unwrap();
                }
                SEGFAULT => {
                    self.output.write(b"Segfault").unwrap();
                }
                UNKNOWN_ERROR => {
                    self.output.write(b"Unknown Error").unwrap();
                }
                _ => debug!("no default handler"),
            }

            if events::is_critical(event) {
                self.terminate();
            }
        } else {
            debug!("handler is set");
            let pc = self.get_register(PC);
            self.stack_push_word(pc);
            self.stack_push(argument);
            self.set_register(PC, handler);
        }
    }

    fn process_events(&mut self) {
        let nothing_to_process = self.terminated || self.event_queue().is_empty();
        if !nothing_to_process {
            let (event, argument) = self.event_queue_pop();
            self.process_event(event, argument);
        }
    }

    fn event_queue_push(&mut self, event: u8, argument: u8) {
        self.decrement_register(EP);
        let ep = self.get_register(EP);
        self.memory.put(ep, argument);

        self.decrement_register(EP);
        let ep = self.get_register(EP);
        self.memory.put(ep, event);
    }

    fn event_queue_pop(&mut self) -> (u8, u8) {
        let ee = self.get_register(EE);
        let ep = self.get_register(EP);
        assert_lt!(ep, ee);

        self.decrement_register(EE);
        let ee = self.get_register(EE);
        let argument = self.memory.get(ee);

        self.decrement_register(EE);
        let ee = self.get_register(EE);
        let event = self.memory.get(ee);

        if ep == ee {
            let event_queue_end = self.memory.event_queue_end;
            self.set_register(EP, event_queue_end);
            self.set_register(EE, event_queue_end);
        }

        (event, argument)
    }

    fn next_code_byte(&mut self) -> u8 {
        let code_begin = self.get_register(PC);
        let value = self.memory.get(code_begin);
        self.increment_register(PC);
        value
    }

    fn get_register(&self, id: u8) -> Word {
        self.registers[id as usize]
    }

    fn set_register(&mut self, id: u8, value: Word) {
        debug!("set r{:x} = {}", id, to_hex!(value));
        self.registers[id as usize] = value;
    }

    fn increment_register(&mut self, id: u8) {
        self.registers[id as usize] += 1;
    }

    fn decrement_register(&mut self, id: u8) {
        self.registers[id as usize] -= 1;
    }

    fn stack_top(&self) -> u8 {
        let sp = self.get_register(SP);
        self.memory.get(sp)
    }

    fn stack_pop(&mut self) -> u8 {
        debug!("stack_pop {} from [{}]",
               to_hex!(self.stack_top()),
               data_to_hex(self.stack()));
        let value = self.stack_top();
        self.increment_register(SP);
        value
    }

    fn stack_push(&mut self, value: u8) {
        debug!("stack_push {} to [{}]",
               to_hex!(value),
               data_to_hex(self.stack()));
        self.decrement_register(SP);
        let sp = self.get_register(SP);
        self.memory.put(sp, value);
    }

    fn stack_push_word(&mut self, value: Word) {
        debug!("stack_push_word to [{}]", data_to_hex(self.stack()));
        unimplemented!()
    }
}

impl<R: Read, W: Write> fmt::Debug for VM<R, W> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "PC={} SP={} IR={} EP={} stack=[{}] code=[{}]",
               to_hex!(self.get_register(PC)),
               to_hex!(self.get_register(SP)),
               to_hex!(self.get_register(IR)),
               to_hex!(self.get_register(EP)),
               data_to_hex(self.stack()),
               data_to_hex(self.code()))
    }
}
<commit_msg>implement STORE<commit_after>use common::*;
use env_logger;
use std::fmt;
use std::io::{Read, Write, Error, ErrorKind, Result};
use std::num::Wrapping;

mod events;
mod memory;
mod modes;
mod opcodes;
mod registers;

use self::events::*;
use self::memory::*;
use self::modes::*;
use self::opcodes::*;
use self::registers::*;

include!("tests.rs");

pub struct VM<R: Read, W: Write> {
    input: R,
    output: W,

    registers: Registers,
    memory: Memory,
    terminated: bool,
}

impl<R: Read, W: Write> VM<R, W> {
    pub fn new(input: R, output: W, executable: Data) -> Self {
        let memory = Memory::from_executable(executable);

        VM {
            input: input,
            output: output,
            registers: [0; REGISTERS as usize],
            memory: memory,
            terminated: false,
        }
    }

    pub fn run(&mut self) {
        self.set_register(PC, CODE_OFFSET as Word);

        let stack_end = self.memory.stack_end;
        self.set_register(SP, stack_end);

        let event_queue_end = self.memory.event_queue_end;
        self.set_register(EP, event_queue_end);
        self.set_register(EE, event_queue_end);

        let mut args = vec![];
        while !self.terminated {
            let pc = self.get_register(PC);
            if !self.memory.is_in_code(pc) && self.event_queue().is_empty() {
                self.terminate();
            } else {
                self.fetch()
                    .decode(&mut args)
                    .execute(&args)
                    .process_events();
                args.clear();
            }
        }

        self.output.flush().unwrap();
    }

    pub fn code(&self) -> DataSlice {
        self.memory.code()
    }

    pub fn data(&self) -> DataSlice {
        self.memory.data()
    }

    pub fn stack(&self) -> DataSlice {
        let sp = self.get_register(SP);
        self.memory.stack(sp)
    }

    pub fn event_queue(&self) -> DataSlice {
        let ep = self.get_register(EP);
        let ee = self.get_register(EE);
        self.memory.event_queue(ep, ee)
    }

    fn terminate(&mut self) {
        debug!("terminate {:?}", self);
        self.terminated = true;
    }

    fn fetch(&mut self) -> &mut Self {
        debug!("fetch {:?}", self);

        let opcode = self.next_code_byte() as Word;
        self.set_register(IR, opcode);
        self
    }

    fn decode(&mut self, args: &mut Data) -> &mut Self {
        debug!("decode {:?}", self);

        let opcode = self.get_register(IR) as u8;
        match opcode {
            ADD | SUB | MUL | DIV | MOD | SWP => {
                if self.stack().len() >= 2 {
                    args.push(self.stack_pop());
                    args.push(self.stack_pop());
                }
            }
            INC | DEC => {
                if !self.stack().is_empty() {
                    args.push(self.stack_pop());
                }
            }
            PUSH => args.push(self.next_code_byte()),
            POP | NOP => (),
            LOAD | STORE => {
                args.push(self.next_code_byte());
                args.push(self.next_code_byte());
                args.push(self.next_code_byte());
            }
            EMIT => {
                let event = self.next_code_byte();
                let argument = if self.stack().is_empty() {
                    0x00
                } else {
                    self.stack_top()
                };
                args.push(event);
                args.push(argument);
            }
            _ => unimplemented!(),
        }

        self
    }

    fn execute(&mut self, args: DataSlice) -> &mut Self {
        debug!("execute {:?}", self);

        let opcode = self.get_register(IR) as u8;
        match opcode {
            NOP => (),
            ADD => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let value = Wrapping(args[0]) + Wrapping(args[1]);
                    self.stack_push(value.0);
                }
            }
            SUB => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let value = Wrapping(args[0]) - Wrapping(args[1]);
                    self.stack_push(value.0);
                }
            }
            MUL => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let value = Wrapping(args[0]) * Wrapping(args[1]);
                    self.stack_push(value.0);
                }
            }
            DIV => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else if args[1] == 0 {
                    self.process_event(UNKNOWN_ERROR, 0x00);
                } else {
                    let value = Wrapping(args[0]) / Wrapping(args[1]);
                    self.stack_push(value.0);
                }
            }
            MOD => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else if args[1] == 0 {
                    self.process_event(UNKNOWN_ERROR, 0x00);
                } else {
                    let value = Wrapping(args[0]) % Wrapping(args[1]);
                    self.stack_push(value.0);
                }
            }
            INC => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let value = Wrapping(args[0]) + Wrapping(1);
                    self.stack_push(value.0);
                }
            }
            DEC => {
                if args.is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let value = Wrapping(args[0]) - Wrapping(1);
                    self.stack_push(value.0);
                }
            }
            PUSH => {
                if self.get_register(SP) <= self.memory.stack_begin {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    self.stack_push(args[0]);
                }
            }
            POP => {
                if self.stack().is_empty() {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    let _ = self.stack_pop();
                }
            }
            SWP => {
                if args.len() < 2 {
                    self.process_event(SEGFAULT, 0x00);
                } else {
                    self.stack_push(args[0]);
                    self.stack_push(args[1]);
                }
            }
            LOAD => {
                match self.load_data(args) {
                    Some(value) => self.stack_push(value),
                    None => self.process_event(SEGFAULT, 0x00),
                }
            }
            STORE => {
                if self.store_data(args).is_err() {
                    self.process_event(SEGFAULT, 0x0);
                }
            }
            EMIT => {
                let event = args[0];
                let argument = args[1];
                if events::is_critical(event) {
                    self.process_event(event, argument);
                } else {
                    self.event_queue_push(event, argument);
                }
            }
            _ => unimplemented!(),
        }

        self
    }

    fn load_data(&self, args: DataSlice) -> Option<u8> {
        self.extract_data_ptr(args)
            .map(|ptr| self.memory.get(ptr))
    }

    fn store_data(&mut self, args: DataSlice) -> Result<()> {
        let e = Error::new(ErrorKind::InvalidInput, "");

        match self.extract_ptr(args) {
            Some((ptr, with_offset)) => {
                let value = if with_offset {
                    if self.stack().len() < 2 {
                        return Err(e);
                    } else {
                        self.stack()[1]
                    }
                } else {
                    self.stack()[0]
                };

                self.memory.put(ptr, value);
                Ok(())
            }
            None => Err(e),
        }
    }

    fn extract_data_ptr(&self, args: DataSlice) -> Option<Word> {
        self.extract_ptr(args)
            .and_then(|(ptr, _)| if self.memory.is_in_data(ptr) {
                Some(ptr)
            } else {
                None
            })
    }

    fn extract_ptr(&self, args: DataSlice) -> Option<(Word, bool)> {
        let mode = args[0];
        let ptr = Memory::read_word_from(&args, 1);

        let mut with_offset = false;

        let updated_ptr = match mode {
            PTR => ptr,
            PTR_WITH_OFFSET => {
                with_offset = true;

                if self.stack().is_empty() {
                    return None;
                } else {
                    let offset = self.stack_top() as Word;
                    ptr + offset
                }
            }
            _ => unreachable!(),
        };

        Some((updated_ptr, with_offset))
    }

    fn process_event(&mut self, event: u8, argument: u8) {
        debug!("process_event event={} argument={}",
               to_hex!(event),
               to_hex!(argument));

        let handler = self.memory.get_event_handler(event);
        if handler == 0 {
            debug!("handler is NOT set");
            match event {
                INPUT => {
                    let mut buffer = [0; 1];
                    let _ = self.input.read(&mut buffer).unwrap();
                    self.stack_push(buffer[0]);
                }
                OUTPUT => {
                    self.output.write(&[argument]).unwrap();
                }
                SEGFAULT => {
                    self.output.write(b"Segfault").unwrap();
                }
                UNKNOWN_ERROR => {
                    self.output.write(b"Unknown Error").unwrap();
                }
                _ => debug!("no default handler"),
            }

            if events::is_critical(event) {
                self.terminate();
            }
        } else {
            debug!("handler is set");
            let pc = self.get_register(PC);
            self.stack_push_word(pc);
            self.stack_push(argument);
            self.set_register(PC, handler);
        }
    }

    fn process_events(&mut self) {
        let nothing_to_process = self.terminated || self.event_queue().is_empty();
        if !nothing_to_process {
            let (event, argument) = self.event_queue_pop();
            self.process_event(event, argument);
        }
    }

    fn event_queue_push(&mut self, event: u8, argument: u8) {
        self.decrement_register(EP);
        let ep = self.get_register(EP);
        self.memory.put(ep, argument);

        self.decrement_register(EP);
        let ep = self.get_register(EP);
        self.memory.put(ep, event);
    }

    fn event_queue_pop(&mut self) -> (u8, u8) {
        let ee = self.get_register(EE);
        let ep = self.get_register(EP);
        assert_lt!(ep, ee);

        self.decrement_register(EE);
        let ee = self.get_register(EE);
        let argument = self.memory.get(ee);

        self.decrement_register(EE);
        let ee = self.get_register(EE);
        let event = self.memory.get(ee);

        if ep == ee {
            let event_queue_end = self.memory.event_queue_end;
            self.set_register(EP, event_queue_end);
            self.set_register(EE, event_queue_end);
        }

        (event, argument)
    }

    fn next_code_byte(&mut self) -> u8 {
        let code_begin = self.get_register(PC);
        let value = self.memory.get(code_begin);
        self.increment_register(PC);
        value
    }

    fn get_register(&self, id: u8) -> Word {
        self.registers[id as usize]
    }

    fn set_register(&mut self, id: u8, value: Word) {
        debug!("set r{:x} = {}", id, to_hex!(value));
        self.registers[id as usize] = value;
    }

    fn increment_register(&mut self, id: u8) {
        self.registers[id as usize] += 1;
    }

    fn decrement_register(&mut self, id: u8) {
        self.registers[id as usize] -= 1;
    }

    fn stack_top(&self) -> u8 {
        let sp = self.get_register(SP);
        self.memory.get(sp)
    }

    fn stack_pop(&mut self) -> u8 {
        debug!("stack_pop {} from [{}]",
               to_hex!(self.stack_top()),
               data_to_hex(self.stack()));
        let value = self.stack_top();
        self.increment_register(SP);
        value
    }

    fn stack_push(&mut self, value: u8) {
        debug!("stack_push {} to [{}]",
               to_hex!(value),
               data_to_hex(self.stack()));
        self.decrement_register(SP);
        let sp = self.get_register(SP);
        self.memory.put(sp, value);
    }

    fn stack_push_word(&mut self, value: Word) {
        debug!("stack_push_word to [{}]", data_to_hex(self.stack()));
        unimplemented!()
    }
}

impl<R: Read, W: Write> fmt::Debug for VM<R, W> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "PC={} SP={} IR={} EP={} stack=[{}] code=[{}]",
               to_hex!(self.get_register(PC)),
               to_hex!(self.get_register(SP)),
               to_hex!(self.get_register(IR)),
               to_hex!(self.get_register(EP)),
               data_to_hex(self.stack()),
               data_to_hex(self.code()))
    }
}
<|endoftext|>


<commit_before>use std::ops::Drop;

use std::path::PathBuf;
use std::fs::File;
use std::error::Error;

use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use runtime::Runtime;

/*
 * A Temporary file in /tmp where the editor is launched on, so we can grap the contents and put
 * into the store
 */
pub struct TempFile {
    path: Option<PathBuf>,
    file: Option<File>,
}

impl TempFile {

    pub fn new(rt: &Runtime) -> TempFile {
        debug!("Building new TempFile");
        unimplemented!()
    }

    pub fn edit(&mut self, editor: Option<String>) -> TempFile {
        debug!("Editing TempFile");
        unimplemented!()
    }

    pub fn content(&self) -> Result<String, TempFileError> {
        debug!("Fetching content of TempFile");
        unimplemented!()
    }

}

/*
 * Implement Drop, so we ensure to remove the tempfile
 *
 * (is this neccessary if we use a real tempfile)
 */
impl Drop for TempFile {

    fn drop(&mut self) {
        unimplemented!()
    }

}

pub struct TempFileError {
    desc: &'static str,
    caused_by: Option<Box<Error>>,
}

impl TempFileError {

    pub fn new(s: &'static str) -> TempFileError {
        TempFileError {
            desc: s,
            caused_by: None,
        }
    }

    pub fn with_cause(s: &'static str, c: Box<Error>) -> TempFileError {
        TempFileError {
            desc: s,
            caused_by: Some(c),
        }
    }

}

impl Display for TempFileError {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "TempFileError: '{}'", self.desc);
        Ok(())
    }
}

impl Debug for TempFileError {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "TempFileError: '{}'", self.desc);

        if let Some(ref e) = self.caused_by {
            write!(fmt, "  cause: {:?}\n\n", e);
        }

        Ok(())
    }
}

impl Error for TempFileError {

    fn description(&self) -> &str {
        self.desc
    }

    fn cause(&self) -> Option<&Error> {
        self.caused_by.as_ref().map(|e| &**e)
    }

}

<commit_msg>Remove all the crap and implement temp-file editor calling<commit_after>use std::ops::Drop;

use std::path::PathBuf;
use std::fs::File;
use std::error::Error;

use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use runtime::Runtime;

/**
 * A function which lets the user provide content by editing a temp files which gets removed after
 * the function got the content from it.
 */
pub fn let_user_provide_content(rt: &Runtime) -> Option<String> {
    use std::io::Read;
    use std::fs::File;
    use std::process::Command;
    use std::process::Child;

    let filepath        = "/tmp/imag-tmp.md";
    let file_created    = File::create(filepath)
                                .map(|_| true)
                                .unwrap_or(false);

    if !file_created {
        warn!("Could not create temporary file for user input!");
        return None;
    }

    let output = {
        let mut cmd = Command::new(rt.editor());
        cmd.arg(filepath);
        debug!("cmd = {:?}", cmd);
        cmd.spawn()
           .and_then(|child| {
               child.wait_with_output()
            })
    };

    let process_out = output.map_err(|e| {
        error!("Editor call failed");
        debug!("Editor call failed: {:?}", e);
        return None as Option<String>;
    }).unwrap();

    if !process_out.status.success() {
        error!("Editor call failed");
        debug!("status = {:?}", process_out.status);
        debug!("stdout = {:?}", String::from_utf8(process_out.stdout));
        debug!("stderr = {:?}", String::from_utf8(process_out.stderr));
        return None;
    }

    let mut contents = String::new();
    File::open(filepath).map(|mut file| {
        file.read_to_string(&mut contents);
        Some(contents)
    }).unwrap_or(None)
}
<|endoftext|>


<commit_before>use runtime::Runtime;

/**
 * A function which lets the user provide content by editing a temp files which gets removed after
 * the function got the content from it.
 */
pub fn let_user_provide_content(rt: &Runtime) -> Option<String> {
    use std::io::Read;
    use std::fs::File;
    use std::process::Command;

    let filepath        = "/tmp/imag-tmp.md";
    let file_created    = File::create(filepath)
                                .map(|_| true)
                                .unwrap_or(false);

    if !file_created {
        warn!("Could not create temporary file for user input!");
        return None;
    }

    let output = {
        let mut cmd = rt.editor();
        cmd.arg(filepath);
        debug!("cmd = {:?}", cmd);
        cmd.spawn()
           .and_then(|child| {
               child.wait_with_output()
            })
    };

    let process_out = output.map_err(|e| {
        error!("Editor call failed");
        debug!("Editor call failed: {:?}", e);
        return None as Option<String>;
    }).unwrap();

    if !process_out.status.success() {
        error!("Editor call failed");
        debug!("status = {:?}", process_out.status);
        debug!("stdout = {:?}", String::from_utf8(process_out.stdout));
        debug!("stderr = {:?}", String::from_utf8(process_out.stderr));
        return None;
    }

    let mut contents = String::new();
    File::open(filepath).map(|mut file| {
        file.read_to_string(&mut contents);
        Some(contents)
    }).unwrap_or(None)
}
<commit_msg>Add: ui::external::editor::edit_content()<commit_after>use runtime::Runtime;

/**
 * A function which lets the user provide content by editing a temp files which gets removed after
 * the function got the content from it.
 */
pub fn let_user_provide_content(rt: &Runtime) -> Option<String> {
    use std::io::Read;
    use std::fs::File;
    use std::process::Command;

    let filepath        = "/tmp/imag-tmp.md";
    let file_created    = File::create(filepath)
                                .map(|_| true)
                                .unwrap_or(false);

    if !file_created {
        warn!("Could not create temporary file for user input!");
        return None;
    }

    let output = {
        let mut cmd = rt.editor();
        cmd.arg(filepath);
        debug!("cmd = {:?}", cmd);
        cmd.spawn()
           .and_then(|child| {
               child.wait_with_output()
            })
    };

    let process_out = output.map_err(|e| {
        error!("Editor call failed");
        debug!("Editor call failed: {:?}", e);
        return None as Option<String>;
    }).unwrap();

    if !process_out.status.success() {
        error!("Editor call failed");
        debug!("status = {:?}", process_out.status);
        debug!("stdout = {:?}", String::from_utf8(process_out.stdout));
        debug!("stderr = {:?}", String::from_utf8(process_out.stderr));
        return None;
    }

    let mut contents = String::new();
    File::open(filepath).map(|mut file| {
        file.read_to_string(&mut contents);
        Some(contents)
    }).unwrap_or(None)
}

/**
 * Edit some content in a temporary file. If anything failes within this routine, it returns the
 * old content and false.
 * If the editing succeeded, it returns the new content and true
 */
pub fn edit_content(rt: &Runtime, old_content: String) -> (String, bool) {
    use std::io::Read;
    use std::io::Write;
    use std::fs::File;
    use std::process::Command;
    use std::process::exit;

    let filepath = "/tmp/imag-tmp.md";
    {
        let mut file = match File::create(filepath) {
            Ok(f) => f,
            Err(e) => {
                error!("Error creating file {}", filepath);
                debug!("Error creating file at '{}', error = {}", filepath, e);
                exit(1);
            }
        };

        file.write(old_content.as_ref());
    }
    debug!("Ready with putting old content into the file");

    let output = {
        let mut cmd = rt.editor();
        cmd.arg(filepath);
        debug!("cmd = {:?}", cmd);
        cmd.spawn()
           .and_then(|child| child.wait_with_output())
    };

    let process_out = output.map_err(|e| {
        error!("Editor call failed");
        debug!("Editor call failed: {:?}", e);
        return None as Option<String>;
    }).unwrap();

    if !process_out.status.success() {
        error!("Editor call failed");
        debug!("status = {:?}", process_out.status);
        debug!("stdout = {:?}", String::from_utf8(process_out.stdout));
        debug!("stderr = {:?}", String::from_utf8(process_out.stderr));
        return (old_content, false);
    }

    let mut contents = String::new();
    File::open(filepath).map(|mut file| {
        file.read_to_string(&mut contents);
        (contents, true)
    }).unwrap_or((old_content, false))
}

<|endoftext|>


<commit_before>#![allow(nonstandard_style)]

use libc::{c_int, c_void, uintptr_t};

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum _Unwind_Reason_Code {
    _URC_NO_REASON = 0,
    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
    _URC_FATAL_PHASE2_ERROR = 2,
    _URC_FATAL_PHASE1_ERROR = 3,
    _URC_NORMAL_STOP = 4,
    _URC_END_OF_STACK = 5,
    _URC_HANDLER_FOUND = 6,
    _URC_INSTALL_CONTEXT = 7,
    _URC_CONTINUE_UNWIND = 8,
    _URC_FAILURE = 9, // used only by ARM EHABI
}
pub use _Unwind_Reason_Code::*;

pub type _Unwind_Exception_Class = u64;
pub type _Unwind_Word = uintptr_t;
pub type _Unwind_Ptr = uintptr_t;
pub type _Unwind_Trace_Fn =
    extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code;

#[cfg(target_arch = "x86")]
pub const unwinder_private_data_size: usize = 5;

#[cfg(target_arch = "x86_64")]
pub const unwinder_private_data_size: usize = 6;

#[cfg(all(target_arch = "arm", not(target_os = "ios")))]
pub const unwinder_private_data_size: usize = 20;

#[cfg(all(target_arch = "arm", target_os = "ios"))]
pub const unwinder_private_data_size: usize = 5;

#[cfg(target_arch = "aarch64")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "mips")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "mips64")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "s390x")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "sparc64")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(any(target_arch = "riscv64", target_arch = "riscv32")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_os = "emscripten")]
pub const unwinder_private_data_size: usize = 20;

#[cfg(all(target_arch = "hexagon", target_os = "linux"))]
pub const unwinder_private_data_size: usize = 35;

#[repr(C)]
pub struct _Unwind_Exception {
    pub exception_class: _Unwind_Exception_Class,
    pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
    pub private: [_Unwind_Word; unwinder_private_data_size],
}

pub enum _Unwind_Context {}

pub type _Unwind_Exception_Cleanup_Fn =
    extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception);
#[cfg_attr(
    all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
    link(name = "unwind", kind = "static")
)]
extern "C" {
    #[unwind(allowed)]
    pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
    pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
    pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
    pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
    pub fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
    pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
}

cfg_if::cfg_if! {
if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm"))))] {
    // Not ARM EHABI
    #[repr(C)]
    #[derive(Copy, Clone, PartialEq)]
    pub enum _Unwind_Action {
        _UA_SEARCH_PHASE = 1,
        _UA_CLEANUP_PHASE = 2,
        _UA_HANDLER_FRAME = 4,
        _UA_FORCE_UNWIND = 8,
        _UA_END_OF_STACK = 16,
    }
    pub use _Unwind_Action::*;

    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word;
        pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word);
        pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word;
        pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word);
        pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, ip_before_insn: *mut c_int)
                                 -> _Unwind_Word;
        pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
    }

} else {
    // ARM EHABI
    #[repr(C)]
    #[derive(Copy, Clone, PartialEq)]
    pub enum _Unwind_State {
        _US_VIRTUAL_UNWIND_FRAME = 0,
        _US_UNWIND_FRAME_STARTING = 1,
        _US_UNWIND_FRAME_RESUME = 2,
        _US_ACTION_MASK = 3,
        _US_FORCE_UNWIND = 8,
        _US_END_OF_STACK = 16,
    }
    pub use _Unwind_State::*;

    #[repr(C)]
    enum _Unwind_VRS_Result {
        _UVRSR_OK = 0,
        _UVRSR_NOT_IMPLEMENTED = 1,
        _UVRSR_FAILED = 2,
    }
    #[repr(C)]
    enum _Unwind_VRS_RegClass {
        _UVRSC_CORE = 0,
        _UVRSC_VFP = 1,
        _UVRSC_FPA = 2,
        _UVRSC_WMMXD = 3,
        _UVRSC_WMMXC = 4,
    }
    use _Unwind_VRS_RegClass::*;
    #[repr(C)]
    enum _Unwind_VRS_DataRepresentation {
        _UVRSD_UINT32 = 0,
        _UVRSD_VFPX = 1,
        _UVRSD_FPAX = 2,
        _UVRSD_UINT64 = 3,
        _UVRSD_FLOAT = 4,
        _UVRSD_DOUBLE = 5,
    }
    use _Unwind_VRS_DataRepresentation::*;

    pub const UNWIND_POINTER_REG: c_int = 12;
    pub const UNWIND_SP_REG: c_int = 13;
    pub const UNWIND_IP_REG: c_int = 15;

    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
                           regclass: _Unwind_VRS_RegClass,
                           regno: _Unwind_Word,
                           repr: _Unwind_VRS_DataRepresentation,
                           data: *mut c_void)
                           -> _Unwind_VRS_Result;

        fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context,
                           regclass: _Unwind_VRS_RegClass,
                           regno: _Unwind_Word,
                           repr: _Unwind_VRS_DataRepresentation,
                           data: *mut c_void)
                           -> _Unwind_VRS_Result;
    }

    // On Android or ARM/Linux, these are implemented as macros:

    pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word {
        let mut val: _Unwind_Word = 0;
        _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
                        &mut val as *mut _ as *mut c_void);
        val
    }

    pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) {
        let mut value = value;
        _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
                        &mut value as *mut _ as *mut c_void);
    }

    pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context)
                                -> _Unwind_Word {
        let val = _Unwind_GetGR(ctx, UNWIND_IP_REG);
        (val & !1) as _Unwind_Word
    }

    pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context,
                                value: _Unwind_Word) {
        // Propagate thumb bit to instruction pointer
        let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1;
        let value = value | thumb_state;
        _Unwind_SetGR(ctx, UNWIND_IP_REG, value);
    }

    pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
                                    ip_before_insn: *mut c_int)
                                    -> _Unwind_Word {
        *ip_before_insn = 0;
        _Unwind_GetIP(ctx)
    }

    // This function also doesn't exist on Android or ARM/Linux, so make it a no-op
    pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
        pc
    }
}
} // cfg_if!

cfg_if::cfg_if! {
if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
    // Not 32-bit iOS
    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        #[unwind(allowed)]
        pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
        pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
                                 trace_argument: *mut c_void)
                                 -> _Unwind_Reason_Code;
    }
} else {
    // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        #[unwind(allowed)]
        pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
    }

    #[inline]
    pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
        _Unwind_SjLj_RaiseException(exc)
    }
}
} // cfg_if!

cfg_if::cfg_if! {
if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
    // We declare these as opaque types. This is fine since you just need to
    // pass them to _GCC_specific_handler and forget about them.
    pub enum EXCEPTION_RECORD {}
    pub type LPVOID = *mut c_void;
    pub enum CONTEXT {}
    pub enum DISPATCHER_CONTEXT {}
    pub type EXCEPTION_DISPOSITION = c_int;
    type PersonalityFn = unsafe extern "C" fn(version: c_int,
                                              actions: _Unwind_Action,
                                              exception_class: _Unwind_Exception_Class,
                                              exception_object: *mut _Unwind_Exception,
                                              context: *mut _Unwind_Context)
                                              -> _Unwind_Reason_Code;

    extern "C" {
        pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD,
                                establisherFrame: LPVOID,
                                contextRecord: *mut CONTEXT,
                                dispatcherContext: *mut DISPATCHER_CONTEXT,
                                personality: PersonalityFn)
                                -> EXCEPTION_DISPOSITION;
    }
}
} // cfg_if!
<commit_msg>library/unwind: Add missing )<commit_after>#![allow(nonstandard_style)]

use libc::{c_int, c_void, uintptr_t};

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum _Unwind_Reason_Code {
    _URC_NO_REASON = 0,
    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
    _URC_FATAL_PHASE2_ERROR = 2,
    _URC_FATAL_PHASE1_ERROR = 3,
    _URC_NORMAL_STOP = 4,
    _URC_END_OF_STACK = 5,
    _URC_HANDLER_FOUND = 6,
    _URC_INSTALL_CONTEXT = 7,
    _URC_CONTINUE_UNWIND = 8,
    _URC_FAILURE = 9, // used only by ARM EHABI
}
pub use _Unwind_Reason_Code::*;

pub type _Unwind_Exception_Class = u64;
pub type _Unwind_Word = uintptr_t;
pub type _Unwind_Ptr = uintptr_t;
pub type _Unwind_Trace_Fn =
    extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code;

#[cfg(target_arch = "x86")]
pub const unwinder_private_data_size: usize = 5;

#[cfg(target_arch = "x86_64")]
pub const unwinder_private_data_size: usize = 6;

#[cfg(all(target_arch = "arm", not(target_os = "ios")))]
pub const unwinder_private_data_size: usize = 20;

#[cfg(all(target_arch = "arm", target_os = "ios"))]
pub const unwinder_private_data_size: usize = 5;

#[cfg(target_arch = "aarch64")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "mips")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "mips64")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "s390x")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "sparc64")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_os = "emscripten")]
pub const unwinder_private_data_size: usize = 20;

#[cfg(all(target_arch = "hexagon", target_os = "linux"))]
pub const unwinder_private_data_size: usize = 35;

#[repr(C)]
pub struct _Unwind_Exception {
    pub exception_class: _Unwind_Exception_Class,
    pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
    pub private: [_Unwind_Word; unwinder_private_data_size],
}

pub enum _Unwind_Context {}

pub type _Unwind_Exception_Cleanup_Fn =
    extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception);
#[cfg_attr(
    all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
    link(name = "unwind", kind = "static")
)]
extern "C" {
    #[unwind(allowed)]
    pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
    pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
    pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
    pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
    pub fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
    pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
}

cfg_if::cfg_if! {
if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm"))))] {
    // Not ARM EHABI
    #[repr(C)]
    #[derive(Copy, Clone, PartialEq)]
    pub enum _Unwind_Action {
        _UA_SEARCH_PHASE = 1,
        _UA_CLEANUP_PHASE = 2,
        _UA_HANDLER_FRAME = 4,
        _UA_FORCE_UNWIND = 8,
        _UA_END_OF_STACK = 16,
    }
    pub use _Unwind_Action::*;

    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word;
        pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word);
        pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> _Unwind_Word;
        pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word);
        pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, ip_before_insn: *mut c_int)
                                 -> _Unwind_Word;
        pub fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void;
    }

} else {
    // ARM EHABI
    #[repr(C)]
    #[derive(Copy, Clone, PartialEq)]
    pub enum _Unwind_State {
        _US_VIRTUAL_UNWIND_FRAME = 0,
        _US_UNWIND_FRAME_STARTING = 1,
        _US_UNWIND_FRAME_RESUME = 2,
        _US_ACTION_MASK = 3,
        _US_FORCE_UNWIND = 8,
        _US_END_OF_STACK = 16,
    }
    pub use _Unwind_State::*;

    #[repr(C)]
    enum _Unwind_VRS_Result {
        _UVRSR_OK = 0,
        _UVRSR_NOT_IMPLEMENTED = 1,
        _UVRSR_FAILED = 2,
    }
    #[repr(C)]
    enum _Unwind_VRS_RegClass {
        _UVRSC_CORE = 0,
        _UVRSC_VFP = 1,
        _UVRSC_FPA = 2,
        _UVRSC_WMMXD = 3,
        _UVRSC_WMMXC = 4,
    }
    use _Unwind_VRS_RegClass::*;
    #[repr(C)]
    enum _Unwind_VRS_DataRepresentation {
        _UVRSD_UINT32 = 0,
        _UVRSD_VFPX = 1,
        _UVRSD_FPAX = 2,
        _UVRSD_UINT64 = 3,
        _UVRSD_FLOAT = 4,
        _UVRSD_DOUBLE = 5,
    }
    use _Unwind_VRS_DataRepresentation::*;

    pub const UNWIND_POINTER_REG: c_int = 12;
    pub const UNWIND_SP_REG: c_int = 13;
    pub const UNWIND_IP_REG: c_int = 15;

    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
                           regclass: _Unwind_VRS_RegClass,
                           regno: _Unwind_Word,
                           repr: _Unwind_VRS_DataRepresentation,
                           data: *mut c_void)
                           -> _Unwind_VRS_Result;

        fn _Unwind_VRS_Set(ctx: *mut _Unwind_Context,
                           regclass: _Unwind_VRS_RegClass,
                           regno: _Unwind_Word,
                           repr: _Unwind_VRS_DataRepresentation,
                           data: *mut c_void)
                           -> _Unwind_VRS_Result;
    }

    // On Android or ARM/Linux, these are implemented as macros:

    pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word {
        let mut val: _Unwind_Word = 0;
        _Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
                        &mut val as *mut _ as *mut c_void);
        val
    }

    pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) {
        let mut value = value;
        _Unwind_VRS_Set(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
                        &mut value as *mut _ as *mut c_void);
    }

    pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context)
                                -> _Unwind_Word {
        let val = _Unwind_GetGR(ctx, UNWIND_IP_REG);
        (val & !1) as _Unwind_Word
    }

    pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context,
                                value: _Unwind_Word) {
        // Propagate thumb bit to instruction pointer
        let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1;
        let value = value | thumb_state;
        _Unwind_SetGR(ctx, UNWIND_IP_REG, value);
    }

    pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
                                    ip_before_insn: *mut c_int)
                                    -> _Unwind_Word {
        *ip_before_insn = 0;
        _Unwind_GetIP(ctx)
    }

    // This function also doesn't exist on Android or ARM/Linux, so make it a no-op
    pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
        pc
    }
}
} // cfg_if!

cfg_if::cfg_if! {
if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
    // Not 32-bit iOS
    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        #[unwind(allowed)]
        pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
        pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
                                 trace_argument: *mut c_void)
                                 -> _Unwind_Reason_Code;
    }
} else {
    // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
    #[cfg_attr(all(feature = "llvm-libunwind",
                   any(target_os = "fuchsia", target_os = "linux")),
               link(name = "unwind", kind = "static"))]
    extern "C" {
        #[unwind(allowed)]
        pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
    }

    #[inline]
    pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
        _Unwind_SjLj_RaiseException(exc)
    }
}
} // cfg_if!

cfg_if::cfg_if! {
if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
    // We declare these as opaque types. This is fine since you just need to
    // pass them to _GCC_specific_handler and forget about them.
    pub enum EXCEPTION_RECORD {}
    pub type LPVOID = *mut c_void;
    pub enum CONTEXT {}
    pub enum DISPATCHER_CONTEXT {}
    pub type EXCEPTION_DISPOSITION = c_int;
    type PersonalityFn = unsafe extern "C" fn(version: c_int,
                                              actions: _Unwind_Action,
                                              exception_class: _Unwind_Exception_Class,
                                              exception_object: *mut _Unwind_Exception,
                                              context: *mut _Unwind_Context)
                                              -> _Unwind_Reason_Code;

    extern "C" {
        pub fn _GCC_specific_handler(exceptionRecord: *mut EXCEPTION_RECORD,
                                establisherFrame: LPVOID,
                                contextRecord: *mut CONTEXT,
                                dispatcherContext: *mut DISPATCHER_CONTEXT,
                                personality: PersonalityFn)
                                -> EXCEPTION_DISPOSITION;
    }
}
} // cfg_if!
<|endoftext|>


<commit_before>#[cfg(feature = "arbitrary")]
use base::storage::Owned;
#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};

use num::One;
use rand::distributions::{Distribution, Standard};
use rand::Rng;

use alga::general::Real;
use alga::linear::Rotation as AlgaRotation;

use base::allocator::Allocator;
use base::dimension::{DimName, U2, U3};
use base::{DefaultAllocator, Vector2, Vector3};

use geometry::{
    Isometry, Point, Point3, Rotation, Rotation2, Rotation3, Translation, UnitComplex,
    UnitQuaternion,
};

impl<N: Real, D: DimName, R: AlgaRotation<Point<N, D>>> Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Creates a new identity isometry.
    #[inline]
    pub fn identity() -> Self {
        Self::from_parts(Translation::identity(), R::identity())
    }

    /// The isometry that applies the rotation `r` with its axis passing through the point `p`.
    /// This effectively lets `p` invariant.
    #[inline]
    pub fn rotation_wrt_point(r: R, p: Point<N, D>) -> Self {
        let shift = r.transform_vector(&-&p.coords);
        Self::from_parts(Translation::from_vector(shift + p.coords), r)
    }
}

impl<N: Real, D: DimName, R: AlgaRotation<Point<N, D>>> One for Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Creates a new identity isometry.
    #[inline]
    fn one() -> Self {
        Self::identity()
    }
}

impl<N: Real, D: DimName, R> Distribution<Isometry<N, D, R>> for Standard
where
    R: AlgaRotation<Point<N, D>>,
    Standard: Distribution<N> + Distribution<R>,
    DefaultAllocator: Allocator<N, D>,
{
    #[inline]
    fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> Isometry<N, D, R> {
        Isometry::from_parts(rng.gen(), rng.gen())
    }
}

#[cfg(feature = "arbitrary")]
impl<N, D: DimName, R> Arbitrary for Isometry<N, D, R>
where
    N: Real + Arbitrary + Send,
    R: AlgaRotation<Point<N, D>> + Arbitrary + Send,
    Owned<N, D>: Send,
    DefaultAllocator: Allocator<N, D>,
{
    #[inline]
    fn arbitrary<G: Gen>(rng: &mut G) -> Self {
        Self::from_parts(Arbitrary::arbitrary(rng), Arbitrary::arbitrary(rng))
    }
}

/*
 *
 * Constructors for various static dimensions.
 *
 */

// 2D rotation.
impl<N: Real> Isometry<N, U2, Rotation2<N>> {
    /// Creates a new isometry from a translation and a rotation angle.
    #[inline]
    pub fn new(translation: Vector2<N>, angle: N) -> Self {
        Self::from_parts(
            Translation::from_vector(translation),
            Rotation::<N, U2>::new(angle),
        )
    }
}

impl<N: Real> Isometry<N, U2, UnitComplex<N>> {
    /// Creates a new isometry from a translation and a rotation angle.
    #[inline]
    pub fn new(translation: Vector2<N>, angle: N) -> Self {
        Self::from_parts(
            Translation::from_vector(translation),
            UnitComplex::from_angle(angle),
        )
    }
}

// 3D rotation.
macro_rules! isometry_construction_impl(
    ($RotId: ident < $($RotParams: ident),*>, $RRDim: ty, $RCDim: ty) => {
        impl<N: Real> Isometry<N, U3, $RotId<$($RotParams),*>> {
            /// Creates a new isometry from a translation and a rotation axis-angle.
            #[inline]
            pub fn new(translation: Vector3<N>, axisangle: Vector3<N>) -> Self {
                Self::from_parts(
                    Translation::from_vector(translation),
                    $RotId::<$($RotParams),*>::from_scaled_axis(axisangle))
            }

            /// Creates an isometry that corresponds to the local frame of an observer standing at the
            /// point `eye` and looking toward `target`.
            ///
            /// It maps the view direction `target - eye` to the positive `z` axis and the origin to the
            /// `eye`.
            ///
            /// # Arguments
            ///   * eye - The observer position.
            ///   * target - The target position.
            ///   * up - Vertical direction. The only requirement of this parameter is to not be collinear
            ///   to `eye - at`. Non-collinearity is not checked.
            #[inline]
            pub fn new_observer_frame(eye:    &Point3<N>,
                                      target: &Point3<N>,
                                      up:     &Vector3<N>)
                                      -> Self {
                Self::from_parts(
                    Translation::from_vector(eye.coords.clone()),
                    $RotId::new_observer_frame(&(target - eye), up))
            }

            /// Builds a right-handed look-at view matrix.
            ///
            /// This conforms to the common notion of right handed look-at matrix from the computer
            /// graphics community.
            ///
            /// # Arguments
            ///   * eye - The eye position.
            ///   * target - The target position.
            ///   * up - A vector approximately aligned with required the vertical axis. The only
            ///   requirement of this parameter is to not be collinear to `target - eye`.
            #[inline]
            pub fn look_at_rh(eye:    &Point3<N>,
                              target: &Point3<N>,
                              up:     &Vector3<N>)
                              -> Self {
                let rotation = $RotId::look_at_rh(&(target - eye), up);
                let trans    = &rotation * (-eye);

                Self::from_parts(Translation::from_vector(trans.coords), rotation)
            }

            /// Builds a left-handed look-at view matrix.
            ///
            /// This conforms to the common notion of left handed look-at matrix from the computer
            /// graphics community.
            ///
            /// # Arguments
            ///   * eye - The eye position.
            ///   * target - The target position.
            ///   * up - A vector approximately aligned with required the vertical axis. The only
            ///   requirement of this parameter is to not be collinear to `target - eye`.
            #[inline]
            pub fn look_at_lh(eye:    &Point3<N>,
                              target: &Point3<N>,
                              up:     &Vector3<N>)
                              -> Self {
                let rotation = $RotId::look_at_lh(&(target - eye), up);
                let trans    = &rotation * (-eye);

                Self::from_parts(Translation::from_vector(trans.coords), rotation)
            }
        }
    }
);

isometry_construction_impl!(Rotation3<N>, U3, U3);
isometry_construction_impl!(UnitQuaternion<N>, U4, U1);
<commit_msg>Add simple constructors for pure-translation and pure-rotation isometries.<commit_after>#[cfg(feature = "arbitrary")]
use base::storage::Owned;
#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};

use num::One;
use rand::distributions::{Distribution, Standard};
use rand::Rng;

use alga::general::Real;
use alga::linear::Rotation as AlgaRotation;

use base::allocator::Allocator;
use base::dimension::{DimName, U2, U3};
use base::{DefaultAllocator, Vector2, Vector3};

use geometry::{
    Isometry, Point, Point3, Rotation, Rotation2, Rotation3, Translation, UnitComplex,
    UnitQuaternion, Translation2, Translation3
};

impl<N: Real, D: DimName, R: AlgaRotation<Point<N, D>>> Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Creates a new identity isometry.
    #[inline]
    pub fn identity() -> Self {
        Self::from_parts(Translation::identity(), R::identity())
    }

    /// The isometry that applies the rotation `r` with its axis passing through the point `p`.
    /// This effectively lets `p` invariant.
    #[inline]
    pub fn rotation_wrt_point(r: R, p: Point<N, D>) -> Self {
        let shift = r.transform_vector(&-&p.coords);
        Self::from_parts(Translation::from_vector(shift + p.coords), r)
    }
}

impl<N: Real, D: DimName, R: AlgaRotation<Point<N, D>>> One for Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Creates a new identity isometry.
    #[inline]
    fn one() -> Self {
        Self::identity()
    }
}

impl<N: Real, D: DimName, R> Distribution<Isometry<N, D, R>> for Standard
where
    R: AlgaRotation<Point<N, D>>,
    Standard: Distribution<N> + Distribution<R>,
    DefaultAllocator: Allocator<N, D>,
{
    #[inline]
    fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> Isometry<N, D, R> {
        Isometry::from_parts(rng.gen(), rng.gen())
    }
}

#[cfg(feature = "arbitrary")]
impl<N, D: DimName, R> Arbitrary for Isometry<N, D, R>
where
    N: Real + Arbitrary + Send,
    R: AlgaRotation<Point<N, D>> + Arbitrary + Send,
    Owned<N, D>: Send,
    DefaultAllocator: Allocator<N, D>,
{
    #[inline]
    fn arbitrary<G: Gen>(rng: &mut G) -> Self {
        Self::from_parts(Arbitrary::arbitrary(rng), Arbitrary::arbitrary(rng))
    }
}

/*
 *
 * Constructors for various static dimensions.
 *
 */

// 2D rotation.
impl<N: Real> Isometry<N, U2, Rotation2<N>> {
    /// Creates a new isometry from a translation and a rotation angle.
    #[inline]
    pub fn new(translation: Vector2<N>, angle: N) -> Self {
        Self::from_parts(
            Translation::from_vector(translation),
            Rotation::<N, U2>::new(angle),
        )
    }

    /// Creates a new isometry from the given translation coordinates.
    #[inline]
    pub fn translation(x: N, y: N) -> Self {
        Self::new(Vector2::new(x, y), N::zero())
    }

    /// Creates a new isometry from the given rotation angle.
    #[inline]
    pub fn rotation(angle: N) -> Self {
        Self::new(Vector2::zeros(), angle)
    }
}

impl<N: Real> Isometry<N, U2, UnitComplex<N>> {
    /// Creates a new isometry from a translation and a rotation angle.
    #[inline]
    pub fn new(translation: Vector2<N>, angle: N) -> Self {
        Self::from_parts(
            Translation::from_vector(translation),
            UnitComplex::from_angle(angle),
        )
    }

    /// Creates a new isometry from the given translation coordinates.
    #[inline]
    pub fn translation(x: N, y: N) -> Self {
        Self::from_parts(Translation2::new(x, y), UnitComplex::identity())
    }

    /// Creates a new isometry from the given rotation angle.
    #[inline]
    pub fn rotation(angle: N) -> Self {
        Self::new(Vector2::zeros(), angle)
    }
}

// 3D rotation.
macro_rules! isometry_construction_impl(
    ($RotId: ident < $($RotParams: ident),*>, $RRDim: ty, $RCDim: ty) => {
        impl<N: Real> Isometry<N, U3, $RotId<$($RotParams),*>> {
            /// Creates a new isometry from a translation and a rotation axis-angle.
            #[inline]
            pub fn new(translation: Vector3<N>, axisangle: Vector3<N>) -> Self {
                Self::from_parts(
                    Translation::from_vector(translation),
                    $RotId::<$($RotParams),*>::from_scaled_axis(axisangle))
            }

            /// Creates a new isometry from the given translation coordinates.
            #[inline]
            pub fn translation(x: N, y: N, z: N) -> Self {
                Self::from_parts(Translation3::new(x, y, z), $RotId::identity())
            }

            /// Creates a new isometry from the given rotation angle.
            #[inline]
            pub fn rotation(axisangle: Vector3<N>) -> Self {
                Self::new(Vector3::zeros(), axisangle)
            }

            /// Creates an isometry that corresponds to the local frame of an observer standing at the
            /// point `eye` and looking toward `target`.
            ///
            /// It maps the view direction `target - eye` to the positive `z` axis and the origin to the
            /// `eye`.
            ///
            /// # Arguments
            ///   * eye - The observer position.
            ///   * target - The target position.
            ///   * up - Vertical direction. The only requirement of this parameter is to not be collinear
            ///   to `eye - at`. Non-collinearity is not checked.
            #[inline]
            pub fn new_observer_frame(eye:    &Point3<N>,
                                      target: &Point3<N>,
                                      up:     &Vector3<N>)
                                      -> Self {
                Self::from_parts(
                    Translation::from_vector(eye.coords.clone()),
                    $RotId::new_observer_frame(&(target - eye), up))
            }

            /// Builds a right-handed look-at view matrix.
            ///
            /// This conforms to the common notion of right handed look-at matrix from the computer
            /// graphics community.
            ///
            /// # Arguments
            ///   * eye - The eye position.
            ///   * target - The target position.
            ///   * up - A vector approximately aligned with required the vertical axis. The only
            ///   requirement of this parameter is to not be collinear to `target - eye`.
            #[inline]
            pub fn look_at_rh(eye:    &Point3<N>,
                              target: &Point3<N>,
                              up:     &Vector3<N>)
                              -> Self {
                let rotation = $RotId::look_at_rh(&(target - eye), up);
                let trans    = &rotation * (-eye);

                Self::from_parts(Translation::from_vector(trans.coords), rotation)
            }

            /// Builds a left-handed look-at view matrix.
            ///
            /// This conforms to the common notion of left handed look-at matrix from the computer
            /// graphics community.
            ///
            /// # Arguments
            ///   * eye - The eye position.
            ///   * target - The target position.
            ///   * up - A vector approximately aligned with required the vertical axis. The only
            ///   requirement of this parameter is to not be collinear to `target - eye`.
            #[inline]
            pub fn look_at_lh(eye:    &Point3<N>,
                              target: &Point3<N>,
                              up:     &Vector3<N>)
                              -> Self {
                let rotation = $RotId::look_at_lh(&(target - eye), up);
                let trans    = &rotation * (-eye);

                Self::from_parts(Translation::from_vector(trans.coords), rotation)
            }
        }
    }
);

isometry_construction_impl!(Rotation3<N>, U3, U3);
isometry_construction_impl!(UnitQuaternion<N>, U4, U1);
<|endoftext|>


<commit_before>macro_rules! btreeset {
    () => {
        BTreeSet::new()
    };
    ($($value:expr),+) => {
        {
            let mut set = BTreeSet::new();
            $(set.insert($value);)+
            set
        }
    }
}

macro_rules! btreemap {
    () => {
        BTreeMap::new()
    };
    ($($key:expr => $value:expr),+) => {
        {
            let mut map = BTreeMap::new();
            $(map.insert($key, $value);)+
            map
        }
    }
}

macro_rules! hashset {
    () => {
        HashSet::new()
    };
    ($($value:expr),+) => {
        {
            let mut set = HashSet::new();
            $(set.insert($value);)+
            set
        }
    };
    ($hasher:ident @ $($value:expr),+) => {
        {
            use std::hash::BuildHasherDefault;
            let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default());
            $(set.insert($value);)+
            set
        }
    }
}

macro_rules! hashmap {
    () => {
        HashMap::new()
    };
    ($($key:expr => $value:expr),+) => {
        {
            let mut map = HashMap::new();
            $(map.insert($key, $value);)+
            map
        }
    };
    ($hasher:ident @ $($key:expr => $value:expr),+) => {
        {
            use std::hash::BuildHasherDefault;
            let mut map = HashMap::with_hasher(BuildHasherDefault::<$hasher>::default());
            $(map.insert($key, $value);)+
            map
        }
    }
}

macro_rules! seq_impl {
    (.. $first:expr $(,)?) => {
        $first.into_iter()
    };
    (.. $first:expr, $($elem:tt)*) => {
        $first.into_iter().chain(seq!($($elem)*))
    };
    ($first:expr $(,)?) => {
        Some($first).into_iter()
    };
    ($first:expr, $($elem:tt)*) => {
        Some($first).into_iter().chain(seq!($($elem)*))
    }
}

macro_rules! seq {
    ($($tt: tt)*) => {
        seq_impl!($($tt)*).collect::<Vec<_>>()
    };
}
<commit_msg>Clean up test suite's macro formatting<commit_after>macro_rules! btreeset {
    () => {
        BTreeSet::new()
    };
    ($($value:expr),+) => {{
        let mut set = BTreeSet::new();
        $(set.insert($value);)+
        set
    }};
}

macro_rules! btreemap {
    () => {
        BTreeMap::new()
    };
    ($($key:expr => $value:expr),+) => {{
        let mut map = BTreeMap::new();
        $(map.insert($key, $value);)+
        map
    }};
}

macro_rules! hashset {
    () => {
        HashSet::new()
    };
    ($($value:expr),+) => {{
        let mut set = HashSet::new();
        $(set.insert($value);)+
        set
    }};
    ($hasher:ident @ $($value:expr),+) => {{
        use std::hash::BuildHasherDefault;
        let mut set = HashSet::with_hasher(BuildHasherDefault::<$hasher>::default());
        $(set.insert($value);)+
        set
    }};
}

macro_rules! hashmap {
    () => {
        HashMap::new()
    };
    ($($key:expr => $value:expr),+) => {{
        let mut map = HashMap::new();
        $(map.insert($key, $value);)+
        map
    }};
    ($hasher:ident @ $($key:expr => $value:expr),+) => {{
        use std::hash::BuildHasherDefault;
        let mut map = HashMap::with_hasher(BuildHasherDefault::<$hasher>::default());
        $(map.insert($key, $value);)+
        map
    }};
}

macro_rules! seq_impl {
    (.. $first:expr $(,)?) => {
        $first.into_iter()
    };
    (.. $first:expr, $($elem:tt)*) => {
        $first.into_iter().chain(seq!($($elem)*))
    };
    ($first:expr $(,)?) => {
        Some($first).into_iter()
    };
    ($first:expr, $($elem:tt)*) => {
        Some($first).into_iter().chain(seq!($($elem)*))
    };
}

macro_rules! seq {
    ($($tt: tt)*) => {
        seq_impl!($($tt)*).collect::<Vec<_>>()
    };
}
<|endoftext|>


<commit_before>use desync::scheduler::*;

use super::timeout::*;

use std::thread;
use std::time::*;
use std::sync::*;
use std::sync::mpsc::*;

use futures::prelude::*;
use futures::task;
use futures::task::{ArcWake, Poll};
use futures::channel::oneshot;

#[test]
fn schedule_future() {
    timeout(|| {
        use futures::executor;

        let queue       = queue();
        let future      = future_sync(&queue, move || async {
            thread::sleep(Duration::from_millis(100));
            42
        });

        executor::block_on(async {
            assert!(future.await.unwrap() == 42);
        });
    }, 500);
}

#[test]
fn schedule_future_with_no_scheduler_threads() {
    timeout(|| {
        use futures::executor;

        let scheduler   = Scheduler::new();

        // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
        scheduler.set_max_threads(0);
        scheduler.despawn_threads_if_overloaded();

        let queue       = queue();
        let future      = scheduler.future_sync(&queue, move || async {
            thread::sleep(Duration::from_millis(100));
            42
        });

        executor::block_on(async {
            assert!(future.await.unwrap() == 42);
        });
    }, 500);
}

#[test]
fn wake_future_with_no_scheduler_threads() {
    timeout(|| {
        use futures::executor;

        let (tx, rx)    = oneshot::channel::<i32>();
        let scheduler   = Scheduler::new();

        // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
        scheduler.set_max_threads(0);
        scheduler.despawn_threads_if_overloaded();

        // Schedule a future that will block until we send a value
        let queue       = queue();
        let future      = scheduler.future_sync(&queue, move || async {
            rx.await.expect("Receive result")
        });

        // Schedule a thread that will send a value
        thread::spawn(move || {
            // Wait for a bit before sending the result so the future should block
            thread::sleep(Duration::from_millis(100));

            tx.send(42).expect("Send")
        });

        executor::block_on(async {
            assert!(future.await.expect("result") == 42);
        });
    }, 500);
}

#[test]
fn wait_for_future() {
    timeout(|| {
        use futures::executor;

        // We use a oneshot as our future, and a mpsc channel to track progress
        let (tx, rx)                = channel();
        let (future_tx, future_rx)  = oneshot::channel();

        let scheduler   = scheduler();
        let queue       = queue();

        // Start by sending '1' from an async
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(1).unwrap(); });

        // Then send the value sent via our oneshot using a future
        let tx2 = tx.clone();
        let future = scheduler.after(&queue, future_rx,
            move |val| val.map(move |val| { tx2.send(val).unwrap(); 4 }));

        // Then send '3'
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(3).unwrap(); });

        // '1' should be available, but we should otherwise be blocked on the future
        assert!(rx.recv().unwrap() == 1);
        assert!(rx.recv_timeout(Duration::from_millis(100)).is_err());

        // Send '2' to the future
        future_tx.send(2).unwrap();

        executor::block_on(async {
            // Future should resolve to 4
            assert!(future.await.unwrap() == Ok(4));

            // Should receive the '2' from the future, then 3
            assert!(rx.recv_timeout(Duration::from_millis(100)).unwrap() == 2);
            assert!(rx.recv().unwrap() == 3);
        });
    }, 500);
}

#[test]
fn future_waits_for_us() {
    timeout(|| {
        use futures::executor;

        // We use a oneshot as our future, and a mpsc channel to track progress
        let (tx, rx)                = channel();
        let (future_tx, future_rx)  = oneshot::channel();

        let scheduler   = scheduler();
        let queue       = queue();

        // Start by sending '1' from an async
        let tx2 = tx.clone();
        desync(&queue, move || { thread::sleep(Duration::from_millis(100)); tx2.send(1).unwrap(); });

        // Then send the value sent via our oneshot using a future
        let tx2 = tx.clone();
        let future = scheduler.after(&queue, future_rx,
            move |val| val.map(move |val| { tx2.send(val).unwrap(); 4 }));

        // Then send '3'
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(3).unwrap(); });

        // Send '2' to the future
        future_tx.send(2).unwrap();

        executor::block_on(async {
            // Future should resolve to 4
            assert!(future.await.unwrap() == Ok(4));

            // '1' should be available first
            assert!(rx.recv().unwrap() == 1);

            // Should receive the '2' from the future, then 3
            assert!(rx.recv_timeout(Duration::from_millis(100)).unwrap() == 2);
            assert!(rx.recv().unwrap() == 3);
        });
    }, 500);
}

///
/// Used for polling futures to see if they've notified us yet
///
struct TestWaker {
    pub awake: Mutex<bool>
}

impl ArcWake for TestWaker {
    fn wake_by_ref(arc_self: &Arc<Self>) {
        (*arc_self.awake.lock().unwrap()) = true;
    }
}

#[test]
fn poll_two_futures_on_one_queue() {
    // 0 threads so we force the future to act in 'drain' mode
    let scheduler   = Scheduler::new();

    // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
    scheduler.set_max_threads(0);
    scheduler.despawn_threads_if_overloaded();

    // If a single queue has a future on
    let queue           = queue();
    let (done1, recv1)  = oneshot::channel::<()>();
    let (done2, recv2)  = oneshot::channel::<()>();

    let wake1           = Arc::new(TestWaker { awake: Mutex::new(false) });
    let wake2           = Arc::new(TestWaker { awake: Mutex::new(false) });

    // Wait for done1 then done2 to signal
    let mut future_1    = scheduler.future_sync(&queue, move || {
        async move { recv1.await.ok(); }
    });

    let mut future_2    = scheduler.future_sync(&queue, move || {
        async move { recv2.await.ok(); }
    });

    // Poll future 1 then future 2 (as there are no threads to run, we'll use the 'drain on current thread' style, which will return pending as recv is pending)
    let waker_ref           = task::waker_ref(&wake1);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_1.poll_unpin(&mut ctxt) == Poll::Pending);

    // Only future_1 should be 'pollable' at this point (ie, is in the WaitForPoll state from the previous call)
    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Pending);

    // Finish both futures
    done1.send(()).unwrap();

    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    // Poll the other future: it should be pending as it's waiting to be scheduled
    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Pending);

    done2.send(()).unwrap();

    // future_1 should be signalled for polling, future_2 should not (as it can't start until future_1 is finished)
    assert!((*wake2.awake.lock().unwrap()) == false);
    assert!((*wake1.awake.lock().unwrap()) == true);

    // Retrieve the result for future_1
    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_1.poll_unpin(&mut ctxt) == Poll::Ready(Ok(())));

    // Both future 1 and future 2 should have signalled now

    // TODO: this is a possible bug with 0 threads - the thread won't reschedule after future_1 completes, so wake2 will not yet be set
    //          (This is quite a complicated problem: if the drain continued processing jobs until it became pending instead of scheduling
    //          in the background, this would work but the return from poll could be delayed indefinitely)
    // assert!((*wake2.awake.lock().unwrap()) == true);

    // Give the scheduler a chance to run the other future (it will be queued in the background, so this is required for the notification to occur)
    scheduler.set_max_threads(1);
    for _ in 0..100 {
        if *wake2.awake.lock().unwrap() { break; }
        thread::sleep(Duration::from_millis(1));
    }
    assert!((*wake2.awake.lock().unwrap()) == true);

    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    // Should be able to retrieve the result of future_2
    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Ready(Ok(())));

    // TODO: not actually sure if this is bad behaviour or not but if future_2 is polled first, future_1 won't be available until future_2
    //      completes. This is another 0 thread only issue as future_1 will be able to send its notification when the thread pool is available.
}
<commit_msg>Think future1 should poll on wake1?<commit_after>use desync::scheduler::*;

use super::timeout::*;

use std::thread;
use std::time::*;
use std::sync::*;
use std::sync::mpsc::*;

use futures::prelude::*;
use futures::task;
use futures::task::{ArcWake, Poll};
use futures::channel::oneshot;

#[test]
fn schedule_future() {
    timeout(|| {
        use futures::executor;

        let queue       = queue();
        let future      = future_sync(&queue, move || async {
            thread::sleep(Duration::from_millis(100));
            42
        });

        executor::block_on(async {
            assert!(future.await.unwrap() == 42);
        });
    }, 500);
}

#[test]
fn schedule_future_with_no_scheduler_threads() {
    timeout(|| {
        use futures::executor;

        let scheduler   = Scheduler::new();

        // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
        scheduler.set_max_threads(0);
        scheduler.despawn_threads_if_overloaded();

        let queue       = queue();
        let future      = scheduler.future_sync(&queue, move || async {
            thread::sleep(Duration::from_millis(100));
            42
        });

        executor::block_on(async {
            assert!(future.await.unwrap() == 42);
        });
    }, 500);
}

#[test]
fn wake_future_with_no_scheduler_threads() {
    timeout(|| {
        use futures::executor;

        let (tx, rx)    = oneshot::channel::<i32>();
        let scheduler   = Scheduler::new();

        // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
        scheduler.set_max_threads(0);
        scheduler.despawn_threads_if_overloaded();

        // Schedule a future that will block until we send a value
        let queue       = queue();
        let future      = scheduler.future_sync(&queue, move || async {
            rx.await.expect("Receive result")
        });

        // Schedule a thread that will send a value
        thread::spawn(move || {
            // Wait for a bit before sending the result so the future should block
            thread::sleep(Duration::from_millis(100));

            tx.send(42).expect("Send")
        });

        executor::block_on(async {
            assert!(future.await.expect("result") == 42);
        });
    }, 500);
}

#[test]
fn wait_for_future() {
    timeout(|| {
        use futures::executor;

        // We use a oneshot as our future, and a mpsc channel to track progress
        let (tx, rx)                = channel();
        let (future_tx, future_rx)  = oneshot::channel();

        let scheduler   = scheduler();
        let queue       = queue();

        // Start by sending '1' from an async
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(1).unwrap(); });

        // Then send the value sent via our oneshot using a future
        let tx2 = tx.clone();
        let future = scheduler.after(&queue, future_rx,
            move |val| val.map(move |val| { tx2.send(val).unwrap(); 4 }));

        // Then send '3'
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(3).unwrap(); });

        // '1' should be available, but we should otherwise be blocked on the future
        assert!(rx.recv().unwrap() == 1);
        assert!(rx.recv_timeout(Duration::from_millis(100)).is_err());

        // Send '2' to the future
        future_tx.send(2).unwrap();

        executor::block_on(async {
            // Future should resolve to 4
            assert!(future.await.unwrap() == Ok(4));

            // Should receive the '2' from the future, then 3
            assert!(rx.recv_timeout(Duration::from_millis(100)).unwrap() == 2);
            assert!(rx.recv().unwrap() == 3);
        });
    }, 500);
}

#[test]
fn future_waits_for_us() {
    timeout(|| {
        use futures::executor;

        // We use a oneshot as our future, and a mpsc channel to track progress
        let (tx, rx)                = channel();
        let (future_tx, future_rx)  = oneshot::channel();

        let scheduler   = scheduler();
        let queue       = queue();

        // Start by sending '1' from an async
        let tx2 = tx.clone();
        desync(&queue, move || { thread::sleep(Duration::from_millis(100)); tx2.send(1).unwrap(); });

        // Then send the value sent via our oneshot using a future
        let tx2 = tx.clone();
        let future = scheduler.after(&queue, future_rx,
            move |val| val.map(move |val| { tx2.send(val).unwrap(); 4 }));

        // Then send '3'
        let tx2 = tx.clone();
        desync(&queue, move || { tx2.send(3).unwrap(); });

        // Send '2' to the future
        future_tx.send(2).unwrap();

        executor::block_on(async {
            // Future should resolve to 4
            assert!(future.await.unwrap() == Ok(4));

            // '1' should be available first
            assert!(rx.recv().unwrap() == 1);

            // Should receive the '2' from the future, then 3
            assert!(rx.recv_timeout(Duration::from_millis(100)).unwrap() == 2);
            assert!(rx.recv().unwrap() == 3);
        });
    }, 500);
}

///
/// Used for polling futures to see if they've notified us yet
///
struct TestWaker {
    pub awake: Mutex<bool>
}

impl ArcWake for TestWaker {
    fn wake_by_ref(arc_self: &Arc<Self>) {
        (*arc_self.awake.lock().unwrap()) = true;
    }
}

#[test]
fn poll_two_futures_on_one_queue() {
    // 0 threads so we force the future to act in 'drain' mode
    let scheduler   = Scheduler::new();

    // Even with 0 threads, futures should still run (by draining on the current thread as for sync actions)
    scheduler.set_max_threads(0);
    scheduler.despawn_threads_if_overloaded();

    // If a single queue has a future on
    let queue           = queue();
    let (done1, recv1)  = oneshot::channel::<()>();
    let (done2, recv2)  = oneshot::channel::<()>();

    let wake1           = Arc::new(TestWaker { awake: Mutex::new(false) });
    let wake2           = Arc::new(TestWaker { awake: Mutex::new(false) });

    // Wait for done1 then done2 to signal
    let mut future_1    = scheduler.future_sync(&queue, move || {
        async move { recv1.await.ok(); }
    });

    let mut future_2    = scheduler.future_sync(&queue, move || {
        async move { recv2.await.ok(); }
    });

    // Poll future 1 then future 2 (as there are no threads to run, we'll use the 'drain on current thread' style, which will return pending as recv is pending)
    let waker_ref           = task::waker_ref(&wake1);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_1.poll_unpin(&mut ctxt) == Poll::Pending);

    // Only future_1 should be 'pollable' at this point (ie, is in the WaitForPoll state from the previous call)
    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Pending);

    // Finish both futures
    done1.send(()).unwrap();

    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    // Poll the other future: it should be pending as it's waiting to be scheduled
    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Pending);

    done2.send(()).unwrap();

    // future_1 should be signalled for polling, future_2 should not (as it can't start until future_1 is finished)
    assert!((*wake2.awake.lock().unwrap()) == false);
    assert!((*wake1.awake.lock().unwrap()) == true);

    // Retrieve the result for future_1
    let waker_ref           = task::waker_ref(&wake1);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    assert!(future_1.poll_unpin(&mut ctxt) == Poll::Ready(Ok(())));

    // Both future 1 and future 2 should have signalled now

    // TODO: this is a possible bug with 0 threads - the thread won't reschedule after future_1 completes, so wake2 will not yet be set
    //          (This is quite a complicated problem: if the drain continued processing jobs until it became pending instead of scheduling
    //          in the background, this would work but the return from poll could be delayed indefinitely)
    // assert!((*wake2.awake.lock().unwrap()) == true);

    // Give the scheduler a chance to run the other future (it will be queued in the background, so this is required for the notification to occur)
    scheduler.set_max_threads(1);
    for _ in 0..100 {
        if *wake2.awake.lock().unwrap() { break; }
        thread::sleep(Duration::from_millis(1));
    }
    assert!((*wake2.awake.lock().unwrap()) == true);

    let waker_ref           = task::waker_ref(&wake2);
    let mut ctxt            = task::Context::from_waker(&waker_ref);

    // Should be able to retrieve the result of future_2
    assert!(future_2.poll_unpin(&mut ctxt) == Poll::Ready(Ok(())));

    // TODO: not actually sure if this is bad behaviour or not but if future_2 is polled first, future_1 won't be available until future_2
    //      completes. This is another 0 thread only issue as future_1 will be able to send its notification when the thread pool is available.
}
<|endoftext|>