<commit_before>use cgmath::EuclideanSpace;
use gilrs::{Axis, Button, Gilrs};
use std::f64::consts::PI;
use winit::{
    event,
    event_loop::{ControlFlow, EventLoop},
};

fn compute_projection_matrix(width: f32, height: f32) -> cgmath::Matrix4<f32> {
    let aspect = width / height;
    let f = 1.0 / (45.0f32.to_radians() / aspect).tan();
    let near = 0.1;

    #[cfg_attr(rustfmt, rustfmt_skip)]
    cgmath::Matrix4::new(
        f/aspect,  0.0,  0.0,   0.0,
        0.0,       f,    0.0,   0.0,
        0.0,       0.0,  0.0,  -1.0,
        0.0,       0.0,  near,  0.0)
}

fn make_swapchain(
    device: &wgpu::Device,
    surface: &wgpu::Surface,
    width: u32,
    height: u32,
) -> wgpu::SwapChain {
    device.create_swap_chain(
        &surface,
        &wgpu::SwapChainDescriptor {
            usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
            format: wgpu::TextureFormat::Bgra8UnormSrgb,
            width,
            height,
            present_mode: wgpu::PresentMode::Mailbox,
        },
    )
}
fn make_depth_buffer(device: &wgpu::Device, width: u32, height: u32) -> wgpu::TextureView {
    device
        .create_texture(&wgpu::TextureDescriptor {
            size: wgpu::Extent3d { width, height, depth: 1 },
            mip_level_count: 1,
            sample_count: 1,
            dimension: wgpu::TextureDimension::D2,
            format: wgpu::TextureFormat::Depth32Float,
            usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
            label: None,
        })
        .create_default_view()
}

fn main() {
    env_logger::init();

    let mut gilrs = Gilrs::new().unwrap();
    let mut current_gamepad = None;
    for (_id, gamepad) in gilrs.gamepads() {
        current_gamepad = Some(gamepad.id());
    }

    let mapfile = terra::MapFileBuilder::build().unwrap();

    let event_loop = EventLoop::new();
    let instance = wgpu::Instance::new(wgpu::BackendBit::VULKAN);
    let window = winit::window::Window::new(&event_loop).unwrap();
    for monitor in window.available_monitors() {
        if monitor.video_modes().any(|mode| mode.size().width == 1920) {
            window.set_fullscreen(Some(winit::window::Fullscreen::Borderless(monitor)));
            break;
        }
    }
    let mut size = window.inner_size();
    let surface = unsafe { instance.create_surface(&window) };
    let adapter =
        futures::executor::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
            power_preference: wgpu::PowerPreference::Default,
            compatible_surface: Some(&surface),
        }))
        .unwrap();
    let (device, mut queue) = futures::executor::block_on(adapter.request_device(
        &wgpu::DeviceDescriptor {
            features: wgpu::Features::empty(),
            limits: wgpu::Limits::default(),
            shader_validation: true,
        },
        None,
    )).unwrap();
    let mut swap_chain = make_swapchain(&device, &surface, size.width, size.height);
    let mut depth_buffer = make_depth_buffer(&device, size.width, size.height);
    let mut proj = compute_projection_matrix(size.width as f32, size.height as f32);

    let planet_radius = 6371000.0;
    let mut angle = 0.0f64;
    let mut lat = 0.85271f64;
    let mut long = 0.041054f64;
    let mut altitude = 1000000.0f64;

    let mut terrain = terra::Terrain::new(&device, &mut queue, mapfile).unwrap();

    event_loop.run(move |event, _, control_flow| {
        *control_flow = if cfg!(feature = "metal-auto-capture") {
            ControlFlow::Exit
        } else {
            ControlFlow::Poll
        };
        match event {
            event::Event::WindowEvent { event, .. } => match event {
                event::WindowEvent::CloseRequested => {
                    *control_flow = ControlFlow::Exit;
                }
                event::WindowEvent::KeyboardInput {
                    input:
                        event::KeyboardInput {
                            virtual_keycode: Some(keycode),
                            state: event::ElementState::Pressed,
                            ..
                        },
                    ..
                } => match keycode {
                    event::VirtualKeyCode::Escape => *control_flow = ControlFlow::Exit,
                    event::VirtualKeyCode::Space => altitude += 0.1 * altitude,
                    event::VirtualKeyCode::Semicolon => altitude -= 0.1 * altitude,
                    // event::VirtualKeyCode::Left => eye.x -= 50.0,
                    // event::VirtualKeyCode::Right => eye.x += 50.0,
                    // event::VirtualKeyCode::Up => eye.z -= 50.0,
                    // event::VirtualKeyCode::Down => eye.z += 50.0,
                    _ => {}
                },
                event::WindowEvent::Resized(new_size) => {
                    size = new_size;
                    swap_chain = make_swapchain(&device, &surface, size.width, size.height);
                    depth_buffer = make_depth_buffer(&device, size.width, size.height);
                    proj = compute_projection_matrix(size.width as f32, size.height as f32);
                }
                _ => {}
            },
            event::Event::MainEventsCleared => {
                let frame = &swap_chain
                    .get_next_frame()
                    .unwrap().output.view;

                while let Some(gilrs::Event { id, event: _event, time: _ }) = gilrs.next_event() {
                    current_gamepad = Some(id);
                }
                if let Some(gamepad) = current_gamepad.map(|id| gilrs.gamepad(id)) {
                    lat += angle.cos() * gamepad.value(Axis::LeftStickY) as f64 * 0.01
                        - angle.sin() * gamepad.value(Axis::LeftStickX) as f64 * 0.01;

                    long += -angle.sin() * gamepad.value(Axis::LeftStickY) as f64 * 0.01
                        + angle.cos() * gamepad.value(Axis::LeftStickX) as f64 * 0.01;

                    angle -= gamepad.value(Axis::RightZ) as f64 * 0.01;

                    if gamepad.is_pressed(Button::DPadUp) {
                        altitude += 0.01 * altitude;
                    }
                    if gamepad.is_pressed(Button::DPadDown) {
                        altitude -= 0.01 * altitude;
                    }
                }

                lat = lat.max(-PI).min(PI);
                if long < -PI {
                    long += PI * 2.0;
                }
                if long > PI {
                    long -= PI * 2.0;
                }

                let r = altitude + planet_radius;
                let eye = cgmath::Point3::new(
                    r * lat.cos() * long.cos(),
                    r * lat.cos() * long.sin(),
                    r * lat.sin(),
                );

                let latc = lat + angle.cos() * 0.001;
                let longc = long - angle.sin() * 0.001;

                let center = cgmath::Point3::new(
                    planet_radius * latc.cos() * longc.cos() - eye.x,
                    planet_radius * latc.cos() * longc.sin() - eye.y,
                    planet_radius * latc.sin() - eye.z,
                );
                let up = cgmath::Vector3::new(eye.x as f32, eye.y as f32, eye.z as f32);

                let view = cgmath::Matrix4::look_at(
                    cgmath::Point3::origin(),
                    cgmath::Point3::new(center.x as f32, center.y as f32, center.z as f32),
                    up,
                );

                let view_proj = proj * view;
                let view_proj = mint::ColumnMatrix4 {
                    x: view_proj.x.into(),
                    y: view_proj.y.into(),
                    z: view_proj.z.into(),
                    w: view_proj.w.into(),
                };

                terrain.render(
                    &device,
                    &mut queue,
                    &frame,
                    &depth_buffer,
                    (size.width, size.height),
                    view_proj,
                    eye.into(),
                );
            }
            _ => (),
        }
    });
}
<commit_msg>Add keyboard controls for preview<commit_after>use cgmath::EuclideanSpace;
use gilrs::{Axis, Button, Gilrs};
use std::f64::consts::PI;
use winit::{
    event,
    event_loop::{ControlFlow, EventLoop},
};

fn compute_projection_matrix(width: f32, height: f32) -> cgmath::Matrix4<f32> {
    let aspect = width / height;
    let f = 1.0 / (45.0f32.to_radians() / aspect).tan();
    let near = 0.1;

    #[cfg_attr(rustfmt, rustfmt_skip)]
    cgmath::Matrix4::new(
        f/aspect,  0.0,  0.0,   0.0,
        0.0,       f,    0.0,   0.0,
        0.0,       0.0,  0.0,  -1.0,
        0.0,       0.0,  near,  0.0)
}

fn make_swapchain(
    device: &wgpu::Device,
    surface: &wgpu::Surface,
    width: u32,
    height: u32,
) -> wgpu::SwapChain {
    device.create_swap_chain(
        &surface,
        &wgpu::SwapChainDescriptor {
            usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
            format: wgpu::TextureFormat::Bgra8UnormSrgb,
            width,
            height,
            present_mode: wgpu::PresentMode::Mailbox,
        },
    )
}
fn make_depth_buffer(device: &wgpu::Device, width: u32, height: u32) -> wgpu::TextureView {
    device
        .create_texture(&wgpu::TextureDescriptor {
            size: wgpu::Extent3d { width, height, depth: 1 },
            mip_level_count: 1,
            sample_count: 1,
            dimension: wgpu::TextureDimension::D2,
            format: wgpu::TextureFormat::Depth32Float,
            usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
            label: None,
        })
        .create_default_view()
}

fn main() {
    env_logger::init();

    let mapfile = terra::MapFileBuilder::build().unwrap();

    let event_loop = EventLoop::new();
    let window = winit::window::Window::new(&event_loop).unwrap();
    for monitor in window.available_monitors() {
        if monitor.video_modes().any(|mode| mode.size().width == 1920) {
            window.set_fullscreen(Some(winit::window::Fullscreen::Borderless(monitor)));
            break;
        }
    }
    let instance = wgpu::Instance::new(wgpu::BackendBit::VULKAN);
    let surface = unsafe { instance.create_surface(&window) };
    let adapter =
        futures::executor::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
            power_preference: wgpu::PowerPreference::Default,
            compatible_surface: Some(&surface),
        }))
        .unwrap();
    let (device, mut queue) = futures::executor::block_on(adapter.request_device(
        &wgpu::DeviceDescriptor {
            features: wgpu::Features::empty(),
            limits: wgpu::Limits::default(),
            shader_validation: true,
        },
        None,
    )).unwrap();

    let mut size = window.inner_size();
    let mut swap_chain = make_swapchain(&device, &surface, size.width, size.height);
    let mut depth_buffer = make_depth_buffer(&device, size.width, size.height);
    let mut proj = compute_projection_matrix(size.width as f32, size.height as f32);

    let mut gilrs = Gilrs::new().unwrap();
    let mut current_gamepad = None;
    for (_id, gamepad) in gilrs.gamepads() {
        current_gamepad = Some(gamepad.id());
    }

    let planet_radius = 6371000.0;
    let mut angle = 0.0f64;
    let mut lat = 41.3851f64.to_radians();
    let mut long = 2.1734f64.to_radians();
    let mut altitude = 200000.0f64;

    let mut terrain = terra::Terrain::new(&device, &mut queue, mapfile).unwrap();

    event_loop.run(move |event, _, control_flow| {
        *control_flow = if cfg!(feature = "metal-auto-capture") {
            ControlFlow::Exit
        } else {
            ControlFlow::Poll
        };
        match event {
            event::Event::WindowEvent { event, .. } => match event {
                event::WindowEvent::CloseRequested => {
                    *control_flow = ControlFlow::Exit;
                }
                event::WindowEvent::KeyboardInput {
                    input:
                        event::KeyboardInput {
                            virtual_keycode: Some(keycode),
                            state: event::ElementState::Pressed,
                            ..
                        },
                    ..
                } => match keycode {
                    event::VirtualKeyCode::Escape => *control_flow = ControlFlow::Exit,
                    event::VirtualKeyCode::Space => altitude += 0.1 * altitude,
                    event::VirtualKeyCode::Semicolon => altitude -= 0.1 * altitude,
                    event::VirtualKeyCode::Left => {
                        lat += -angle.sin() * -0.01;
                        long += angle.cos() * -0.01;
                    }
                    event::VirtualKeyCode::Right => {
                        lat += -angle.sin() * 0.01;
                        long += angle.cos() * 0.01;
                    }
                    event::VirtualKeyCode::Up => {
                        lat += angle.cos() * 0.01;
                        long += -angle.sin() * 0.01;
                    }
                    event::VirtualKeyCode::Down => {
                        lat += angle.cos() * -0.01;
                        long += -angle.sin() * -0.01;
                    }
                    _ => {}
                },
                event::WindowEvent::Resized(new_size) => {
                    size = new_size;
                    swap_chain = make_swapchain(&device, &surface, size.width, size.height);
                    depth_buffer = make_depth_buffer(&device, size.width, size.height);
                    proj = compute_projection_matrix(size.width as f32, size.height as f32);
                }
                _ => {}
            },
            event::Event::MainEventsCleared => {
                let frame = &swap_chain
                    .get_next_frame()
                    .unwrap().output.view;

                while let Some(gilrs::Event { id, event: _event, time: _ }) = gilrs.next_event() {
                    current_gamepad = Some(id);
                }
                if let Some(gamepad) = current_gamepad.map(|id| gilrs.gamepad(id)) {
                    lat += angle.cos() * gamepad.value(Axis::LeftStickY) as f64 * 0.01
                        - angle.sin() * gamepad.value(Axis::LeftStickX) as f64 * 0.01;

                    long += -angle.sin() * gamepad.value(Axis::LeftStickY) as f64 * 0.01
                        + angle.cos() * gamepad.value(Axis::LeftStickX) as f64 * 0.01;

                    angle -= gamepad.value(Axis::RightZ) as f64 * 0.01;

                    if gamepad.is_pressed(Button::DPadUp) {
                        altitude += 0.01 * altitude;
                    }
                    if gamepad.is_pressed(Button::DPadDown) {
                        altitude -= 0.01 * altitude;
                    }
                }

                lat = lat.max(-PI).min(PI);
                if long < -PI {
                    long += PI * 2.0;
                }
                if long > PI {
                    long -= PI * 2.0;
                }

                let r = altitude + planet_radius;
                let eye = cgmath::Point3::new(
                    r * lat.cos() * long.cos(),
                    r * lat.cos() * long.sin(),
                    r * lat.sin(),
                );

                let latc = lat + angle.cos() * 0.1;
                let longc = long - angle.sin() * 0.1;

                let center = cgmath::Point3::new(
                    planet_radius * latc.cos() * longc.cos() - eye.x,
                    planet_radius * latc.cos() * longc.sin() - eye.y,
                    planet_radius * latc.sin() - eye.z,
                );
                let up = cgmath::Vector3::new(eye.x as f32, eye.y as f32, eye.z as f32);

                let view = cgmath::Matrix4::look_at(
                    cgmath::Point3::origin(),
                    cgmath::Point3::new(center.x as f32, center.y as f32, center.z as f32),
                    up,
                );

                let view_proj = proj * view;
                let view_proj = mint::ColumnMatrix4 {
                    x: view_proj.x.into(),
                    y: view_proj.y.into(),
                    z: view_proj.z.into(),
                    w: view_proj.w.into(),
                };

                terrain.render(
                    &device,
                    &mut queue,
                    &frame,
                    &depth_buffer,
                    (size.width, size.height),
                    view_proj,
                    eye.into(),
                );
            }
            _ => (),
        }
    });
}
<|endoftext|>


<commit_before>use utils::u256::U256;
use utils::gas::Gas;
use utils::address::Address;
use super::Opcode;
use vm::{Machine, Memory, Stack, PC};
use account::Storage;
use transaction::Transaction;
use blockchain::{Block, Blockchain};

use std::ops::{Add, Sub, Not, Mul, Div, Shr, Shl, BitAnd, BitOr, BitXor};
use crypto::sha3::Sha3;
use crypto::digest::Digest;

fn signed_abs(v: U256) -> U256 {
    let negative: U256 = U256::one() << 256;

    if v >= negative {
        !v + 1.into()
    } else {
        v
    }
}

macro_rules! op2 {
    ( $machine:expr, $op:ident ) => ({
        let op1 = $machine.stack_mut().pop();
        let op2 = $machine.stack_mut().pop();
        $machine.stack_mut().push(op1.$op(op2));
    })
}

macro_rules! op2_ref {
    ( $machine:expr, $op:ident ) => ({
        let op1 = $machine.stack_mut().pop();
        let op2 = $machine.stack_mut().pop();
        $machine.stack_mut().push(op1.$op(&op2).into());
    })
}

impl Opcode {
    pub fn run<M: Machine>(&self, machine: &mut M) {
        let opcode = self.clone();

        match opcode {
            Opcode::STOP => {
                machine.pc_mut().stop();
            },

            Opcode::ADD => op2!(machine, add),
            Opcode::MUL => op2!(machine, mul),
            Opcode::SUB => op2!(machine, sub),

            Opcode::DIV => {
                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();
                if op2 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else {
                    machine.stack_mut().push(op1 / op2);
                }
            },

            Opcode::SDIV => {
                // This is signed division. So the U256 would need to
                // be treated as signed two's complement. We currently
                // convert it to both positive, and then deal with the
                // sign afterwards...

                let negative: U256 = U256::one() << 256;
                // This value is also -2^255 in two's complement.
                let max: U256 = U256::max_value();
                // This value is also -1 in two's complement.

                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();
                if op2 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else if op1 == negative && op2 == max {
                    machine.stack_mut().push(negative);
                } else {
                    let aop1 = signed_abs(op1);
                    let aop2 = signed_abs(op2);
                    let r = op1 / op2;

                    if (op1 < negative && op2 < negative) || (op1 >= negative && op2 >= negative) {
                        machine.stack_mut().push(r);
                    } else {
                        let sr = !r + 1.into();
                        machine.stack_mut().push(sr);
                    }
                }
            },

            Opcode::MOD => {
                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();

                if op2 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else {
                    machine.stack_mut().push(op1 - (op1 / op2) * op2);
                }
            },

            Opcode::SMOD => {
                let negative: U256 = U256::one() << 256;

                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();

                if op2 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else {
                    let aop1 = signed_abs(op1);
                    let aop2 = signed_abs(op2);
                    let r = aop1 - (aop1 / aop2) * aop2;
                    if op1 < negative && op2 < negative {
                        machine.stack_mut().push(r);
                    } else if op1 >= negative && op2 < negative {
                        machine.stack_mut().push(!(op1 + r) + 1.into());
                    } else if op1 < negative && op2 >= negative {
                        machine.stack_mut().push(op1 + r);
                    } else if op1 >= negative && op2 >= negative {
                        machine.stack_mut().push(!r + 1.into());
                    }
                }
            },

            Opcode::ADDMOD => {
                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();
                let op3 = machine.stack_mut().pop();

                if op3 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else {
                    // TODO: Handle the case where op1 + op2 > 2^256
                    let v = op1 + op2;
                    machine.stack_mut().push(v - (v / op3) * op3);
                }
            },

            Opcode::MULMOD => {
                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();
                let op3 = machine.stack_mut().pop();

                if op3 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else {
                    // TODO: Handle the case where op1 * op2 > 2^256
                    let v = op1 * op2;
                    machine.stack_mut().push(v - (v / op3) * op3);
                }
            },

            Opcode::EXP => {
                let op1 = machine.stack_mut().pop();
                let mut op2 = machine.stack_mut().pop();
                let mut r: U256 = 1.into();

                while op2 != 0.into() {
                    r = r * op1;
                    op2 = op2 - 1.into();
                }
                machine.stack_mut().push(r);
            },

            Opcode::SIGNEXTEND => {
                // TODO: Check this confines with the yello paper

                let mut op1 = machine.stack_mut().pop();
                let mut op2 = machine.stack_mut().pop();

                let mut negative: U256 = 1.into();
                let mut s = 0;
                while op2 != 0.into() {
                    negative = U256::one() << s;
                    s = s + 1;
                    op2 = op2 - 1.into();
                }

                if op1 >= negative {
                    while s <= 256 {
                        op1 = op1 + (U256::one() << s);
                        s = s + 1;
                    }
                    machine.stack_mut().push(op1);
                } else {
                    machine.stack_mut().push(op1);
                }
            },

            Opcode::LT => op2_ref!(machine, lt),
            Opcode::GT => op2_ref!(machine, gt),

            Opcode::SLT => {
                let negative = U256::one() << 256;

                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();

                if op1 < negative && op2 < negative {
                    if op1 < op2 {
                        machine.stack_mut().push(1.into());
                    } else {
                        machine.stack_mut().push(0.into());
                    }
                } else if op2 >= negative && op2 >= negative {
                    if op1 < op2 {
                        machine.stack_mut().push(0.into());
                    } else {
                        machine.stack_mut().push(1.into());
                    }
                } else if op1 < negative && op2 >= negative {
                    machine.stack_mut().push(0.into());
                } else {
                    machine.stack_mut().push(1.into());
                }
            },

            Opcode::SGT => {
                let negative = U256::one() << 256;

                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();

                if op1 < negative && op2 < negative {
                    if op1 < op2 {
                        machine.stack_mut().push(0.into());
                    } else {
                        machine.stack_mut().push(1.into());
                    }
                } else if op2 >= negative && op2 >= negative {
                    if op1 < op2 {
                        machine.stack_mut().push(1.into());
                    } else {
                        machine.stack_mut().push(0.into());
                    }
                } else if op1 < negative && op2 >= negative {
                    machine.stack_mut().push(1.into());
                } else {
                    machine.stack_mut().push(0.into());
                }
            },

            Opcode::EQ => op2_ref!(machine, eq),

            Opcode::ISZERO => {
                let op1 = machine.stack_mut().pop();

                if op1 == 0.into() {
                    machine.stack_mut().push(1.into());
                } else {
                    machine.stack_mut().push(0.into());
                }
            },

            Opcode::AND => op2!(machine, bitand),
            Opcode::OR => op2!(machine, bitor),
            Opcode::XOR => op2!(machine, bitxor),

            Opcode::NOT => {
                let op1 = machine.stack_mut().pop();

                machine.stack_mut().push(!op1);
            },

            Opcode::BYTE => {
                let op1 = machine.stack_mut().pop();
                let op2: usize = machine.stack_mut().pop().into(); // 256 / 8
                let mark: U256 = 0xff.into();

                if op2 >= 256 / 8 {
                    machine.stack_mut().push(0.into());
                } else {
                    machine.stack_mut().push((op1 >> (op2 * 8)) & mark);
                }
            },

            Opcode::SHA3 => {
                let mut op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();

                let mut r: [u8; 32] = [0u8; 32];
                let mut sha3 = Sha3::keccak256();

                while op1 != op2 - 1.into() {
                    let val = machine.memory_mut().read(op1);
                    sha3.input(val.as_ref());
                    op1 = op1 + 1.into();
                }
                sha3.result(&mut r);
                machine.stack_mut().push(U256::from(r.as_ref()))
            },

            Opcode::ADDRESS => {
                let address = machine.transaction().callee();
                machine.stack_mut().push(address.into());
            },

            Opcode::BALANCE => {
                let address: Option<Address> = machine.stack_mut().pop().into();
                let balance = address.map_or(None, |address| {
                    machine.block().balance(address)
                }).map_or(U256::zero(), |balance| balance);
                machine.stack_mut().push(balance);
            },

            // TODO: implement opcode 0x21 to 0x4f

            Opcode::POP => {
                machine.stack_mut().pop();
            },

            Opcode::MLOAD => {
                let op1 = machine.stack_mut().pop();
                let val = machine.memory_mut().read(op1);
                // u_i update is automatically handled by Memory.
                machine.stack_mut().push(val);
            },

            Opcode::MSTORE => {
                let op1 = machine.stack_mut().pop(); // Index
                let op2 = machine.stack_mut().pop(); // Data
                // u_i update is automatically handled by Memory.
                machine.memory_mut().write(op1, op2);
            },

            Opcode::SLOAD => {
                let op1 = machine.stack_mut().pop();
                let val = machine.storage_mut().read(op1);
                machine.stack_mut().push(val);
            },

            Opcode::SSTORE => {
                let op1 = machine.stack_mut().pop(); // Index
                let op2 = machine.stack_mut().pop(); // Data
                machine.storage_mut().write(op1, op2);
            }

            Opcode::JUMP => {
                let op1_u: u64 = machine.stack_mut().pop().into();
                machine.pc_mut().jump(op1_u as usize);
            },

            Opcode::JUMPI => {
                let op1_u: u64 = machine.stack_mut().pop().into();
                let op2 = machine.stack_mut().pop();

                if op2 != 0.into() {
                    machine.pc_mut().jump(op1_u as usize);
                }
            },

            Opcode::PC => {
                let position = machine.pc().position();
                machine.stack_mut().push((position - 1).into()); // PC increment for opcode is always an u8.
            },

            Opcode::MSIZE => {
                let active_len = machine.memory().active_len();
                machine.stack_mut().push(active_len.into());
            },

            Opcode::GAS => {
                let gas: U256 = machine.transaction().gas_limit().into();
                machine.stack_mut().push(gas);
            },

            Opcode::JUMPDEST => (), // This operation has no effect on machine state during execution.

            Opcode::PUSH(v) => {
                let val = machine.pc_mut().read(v);
                machine.stack_mut().push(val);
            },

            Opcode::DUP(v) => {
                let val = machine.stack().peek(v - 1);
                machine.stack_mut().push(val);
            },

            Opcode::SWAP(v) => {
                let val1 = machine.stack().peek(0);
                let val2 = machine.stack().peek(v);
                machine.stack_mut().set(0, val2);
                machine.stack_mut().set(v, val1);
            },

            // TODO: Implement log entries LOG0, LOG1, LOG2, LOG3, LOG4

            // TODO: Implement system operations 0xf0 to 0xff

            _ => {
                unimplemented!();
            }
        }
    }
}
<commit_msg>Problem: ORIGIN and CALLER are not implemented Solution: Implement them!<commit_after>use utils::u256::U256;
use utils::gas::Gas;
use utils::address::Address;
use super::Opcode;
use vm::{Machine, Memory, Stack, PC};
use account::Storage;
use transaction::Transaction;
use blockchain::{Block, Blockchain};

use std::ops::{Add, Sub, Not, Mul, Div, Shr, Shl, BitAnd, BitOr, BitXor};
use crypto::sha3::Sha3;
use crypto::digest::Digest;

fn signed_abs(v: U256) -> U256 {
    let negative: U256 = U256::one() << 256;

    if v >= negative {
        !v + 1.into()
    } else {
        v
    }
}

macro_rules! op2 {
    ( $machine:expr, $op:ident ) => ({
        let op1 = $machine.stack_mut().pop();
        let op2 = $machine.stack_mut().pop();
        $machine.stack_mut().push(op1.$op(op2));
    })
}

macro_rules! op2_ref {
    ( $machine:expr, $op:ident ) => ({
        let op1 = $machine.stack_mut().pop();
        let op2 = $machine.stack_mut().pop();
        $machine.stack_mut().push(op1.$op(&op2).into());
    })
}

impl Opcode {
    pub fn run<M: Machine>(&self, machine: &mut M) {
        let opcode = self.clone();

        match opcode {
            Opcode::STOP => {
                machine.pc_mut().stop();
            },

            Opcode::ADD => op2!(machine, add),
            Opcode::MUL => op2!(machine, mul),
            Opcode::SUB => op2!(machine, sub),

            Opcode::DIV => {
                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();
                if op2 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else {
                    machine.stack_mut().push(op1 / op2);
                }
            },

            Opcode::SDIV => {
                // This is signed division. So the U256 would need to
                // be treated as signed two's complement. We currently
                // convert it to both positive, and then deal with the
                // sign afterwards...

                let negative: U256 = U256::one() << 256;
                // This value is also -2^255 in two's complement.
                let max: U256 = U256::max_value();
                // This value is also -1 in two's complement.

                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();
                if op2 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else if op1 == negative && op2 == max {
                    machine.stack_mut().push(negative);
                } else {
                    let aop1 = signed_abs(op1);
                    let aop2 = signed_abs(op2);
                    let r = op1 / op2;

                    if (op1 < negative && op2 < negative) || (op1 >= negative && op2 >= negative) {
                        machine.stack_mut().push(r);
                    } else {
                        let sr = !r + 1.into();
                        machine.stack_mut().push(sr);
                    }
                }
            },

            Opcode::MOD => {
                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();

                if op2 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else {
                    machine.stack_mut().push(op1 - (op1 / op2) * op2);
                }
            },

            Opcode::SMOD => {
                let negative: U256 = U256::one() << 256;

                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();

                if op2 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else {
                    let aop1 = signed_abs(op1);
                    let aop2 = signed_abs(op2);
                    let r = aop1 - (aop1 / aop2) * aop2;
                    if op1 < negative && op2 < negative {
                        machine.stack_mut().push(r);
                    } else if op1 >= negative && op2 < negative {
                        machine.stack_mut().push(!(op1 + r) + 1.into());
                    } else if op1 < negative && op2 >= negative {
                        machine.stack_mut().push(op1 + r);
                    } else if op1 >= negative && op2 >= negative {
                        machine.stack_mut().push(!r + 1.into());
                    }
                }
            },

            Opcode::ADDMOD => {
                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();
                let op3 = machine.stack_mut().pop();

                if op3 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else {
                    // TODO: Handle the case where op1 + op2 > 2^256
                    let v = op1 + op2;
                    machine.stack_mut().push(v - (v / op3) * op3);
                }
            },

            Opcode::MULMOD => {
                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();
                let op3 = machine.stack_mut().pop();

                if op3 == 0.into() {
                    machine.stack_mut().push(0.into());
                } else {
                    // TODO: Handle the case where op1 * op2 > 2^256
                    let v = op1 * op2;
                    machine.stack_mut().push(v - (v / op3) * op3);
                }
            },

            Opcode::EXP => {
                let op1 = machine.stack_mut().pop();
                let mut op2 = machine.stack_mut().pop();
                let mut r: U256 = 1.into();

                while op2 != 0.into() {
                    r = r * op1;
                    op2 = op2 - 1.into();
                }
                machine.stack_mut().push(r);
            },

            Opcode::SIGNEXTEND => {
                // TODO: Check this confines with the yello paper

                let mut op1 = machine.stack_mut().pop();
                let mut op2 = machine.stack_mut().pop();

                let mut negative: U256 = 1.into();
                let mut s = 0;
                while op2 != 0.into() {
                    negative = U256::one() << s;
                    s = s + 1;
                    op2 = op2 - 1.into();
                }

                if op1 >= negative {
                    while s <= 256 {
                        op1 = op1 + (U256::one() << s);
                        s = s + 1;
                    }
                    machine.stack_mut().push(op1);
                } else {
                    machine.stack_mut().push(op1);
                }
            },

            Opcode::LT => op2_ref!(machine, lt),
            Opcode::GT => op2_ref!(machine, gt),

            Opcode::SLT => {
                let negative = U256::one() << 256;

                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();

                if op1 < negative && op2 < negative {
                    if op1 < op2 {
                        machine.stack_mut().push(1.into());
                    } else {
                        machine.stack_mut().push(0.into());
                    }
                } else if op2 >= negative && op2 >= negative {
                    if op1 < op2 {
                        machine.stack_mut().push(0.into());
                    } else {
                        machine.stack_mut().push(1.into());
                    }
                } else if op1 < negative && op2 >= negative {
                    machine.stack_mut().push(0.into());
                } else {
                    machine.stack_mut().push(1.into());
                }
            },

            Opcode::SGT => {
                let negative = U256::one() << 256;

                let op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();

                if op1 < negative && op2 < negative {
                    if op1 < op2 {
                        machine.stack_mut().push(0.into());
                    } else {
                        machine.stack_mut().push(1.into());
                    }
                } else if op2 >= negative && op2 >= negative {
                    if op1 < op2 {
                        machine.stack_mut().push(1.into());
                    } else {
                        machine.stack_mut().push(0.into());
                    }
                } else if op1 < negative && op2 >= negative {
                    machine.stack_mut().push(1.into());
                } else {
                    machine.stack_mut().push(0.into());
                }
            },

            Opcode::EQ => op2_ref!(machine, eq),

            Opcode::ISZERO => {
                let op1 = machine.stack_mut().pop();

                if op1 == 0.into() {
                    machine.stack_mut().push(1.into());
                } else {
                    machine.stack_mut().push(0.into());
                }
            },

            Opcode::AND => op2!(machine, bitand),
            Opcode::OR => op2!(machine, bitor),
            Opcode::XOR => op2!(machine, bitxor),

            Opcode::NOT => {
                let op1 = machine.stack_mut().pop();

                machine.stack_mut().push(!op1);
            },

            Opcode::BYTE => {
                let op1 = machine.stack_mut().pop();
                let op2: usize = machine.stack_mut().pop().into(); // 256 / 8
                let mark: U256 = 0xff.into();

                if op2 >= 256 / 8 {
                    machine.stack_mut().push(0.into());
                } else {
                    machine.stack_mut().push((op1 >> (op2 * 8)) & mark);
                }
            },

            Opcode::SHA3 => {
                let mut op1 = machine.stack_mut().pop();
                let op2 = machine.stack_mut().pop();

                let mut r: [u8; 32] = [0u8; 32];
                let mut sha3 = Sha3::keccak256();

                while op1 != op2 - 1.into() {
                    let val = machine.memory_mut().read(op1);
                    sha3.input(val.as_ref());
                    op1 = op1 + 1.into();
                }
                sha3.result(&mut r);
                machine.stack_mut().push(U256::from(r.as_ref()))
            },

            Opcode::ADDRESS => {
                let address = machine.transaction().callee();
                machine.stack_mut().push(address.into());
            },

            Opcode::BALANCE => {
                let address: Option<Address> = machine.stack_mut().pop().into();
                let balance = address.map_or(None, |address| {
                    machine.block().balance(address)
                }).map_or(U256::zero(), |balance| balance);
                machine.stack_mut().push(balance);
            },

            Opcode::ORIGIN => {
                let address = machine.transaction().originator();
                machine.stack_mut().push(address.into());
            },

            Opcode::CALLER => {
                let address = machine.transaction().sender();
                machine.stack_mut().push(address.into());
            },

            // TODO: implement opcode 0x21 to 0x4f

            Opcode::POP => {
                machine.stack_mut().pop();
            },

            Opcode::MLOAD => {
                let op1 = machine.stack_mut().pop();
                let val = machine.memory_mut().read(op1);
                // u_i update is automatically handled by Memory.
                machine.stack_mut().push(val);
            },

            Opcode::MSTORE => {
                let op1 = machine.stack_mut().pop(); // Index
                let op2 = machine.stack_mut().pop(); // Data
                // u_i update is automatically handled by Memory.
                machine.memory_mut().write(op1, op2);
            },

            Opcode::SLOAD => {
                let op1 = machine.stack_mut().pop();
                let val = machine.storage_mut().read(op1);
                machine.stack_mut().push(val);
            },

            Opcode::SSTORE => {
                let op1 = machine.stack_mut().pop(); // Index
                let op2 = machine.stack_mut().pop(); // Data
                machine.storage_mut().write(op1, op2);
            }

            Opcode::JUMP => {
                let op1_u: u64 = machine.stack_mut().pop().into();
                machine.pc_mut().jump(op1_u as usize);
            },

            Opcode::JUMPI => {
                let op1_u: u64 = machine.stack_mut().pop().into();
                let op2 = machine.stack_mut().pop();

                if op2 != 0.into() {
                    machine.pc_mut().jump(op1_u as usize);
                }
            },

            Opcode::PC => {
                let position = machine.pc().position();
                machine.stack_mut().push((position - 1).into()); // PC increment for opcode is always an u8.
            },

            Opcode::MSIZE => {
                let active_len = machine.memory().active_len();
                machine.stack_mut().push(active_len.into());
            },

            Opcode::GAS => {
                let gas: U256 = machine.transaction().gas_limit().into();
                machine.stack_mut().push(gas);
            },

            Opcode::JUMPDEST => (), // This operation has no effect on machine state during execution.

            Opcode::PUSH(v) => {
                let val = machine.pc_mut().read(v);
                machine.stack_mut().push(val);
            },

            Opcode::DUP(v) => {
                let val = machine.stack().peek(v - 1);
                machine.stack_mut().push(val);
            },

            Opcode::SWAP(v) => {
                let val1 = machine.stack().peek(0);
                let val2 = machine.stack().peek(v);
                machine.stack_mut().set(0, val2);
                machine.stack_mut().set(v, val1);
            },

            // TODO: Implement log entries LOG0, LOG1, LOG2, LOG3, LOG4

            // TODO: Implement system operations 0xf0 to 0xff

            _ => {
                unimplemented!();
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>dx12: Optimize cpu descriptor handle allocation<commit_after><|endoftext|>


<commit_before>use std::os::getenv;
use std::rc::RcMut;

use simplepattern::ParameterDictionary;
use simplepattern::SimplePattern;
use simplepattern::PatternMatcher;

pub mod simplepattern;
struct HttpContext{
    request: Request,
    response: Response,
}

impl HttpContext{
    fn create() -> HttpContext{
        HttpContext{
            request: Request::populate(),
            response: Response::new()
        }
    }
}

struct Request {
    path: ~str,
    querystring: ~str
}

impl Request {
    fn populate() -> Request {
        Request{
            path: getenv("PATH_INFO").unwrap_or(~""),
            querystring: getenv("QUERY_STRING").unwrap_or(~"")
        }
    }
}

struct Response{
    contenttype: ~str,
    body: ~str
}

impl Response{
    fn new() -> Response{
        Response{contenttype: ~"text/plain", body: ~""}
    }
}

struct Route {
    matcher: ~PatternMatcher,
    handler: ~fn(&mut ControllerContext)
}

struct Router{
    routes: ~[Route],
}

impl Router{
    fn new() -> Router{
        Router{routes: ~[]}
    }
    fn add(&mut self, r: ~Route){
        self.routes.push(*r);
    }
    fn execute(&mut self, c: &mut HttpContext) {
        for route in self.routes.iter(){
            let res=route.matcher.matches(c.request.path);

            if(res.is_match){
                (route.handler)(&mut ControllerContext{http: c, router: self, route_params: res.params});
                return;
            }
        }
        default_handler(&mut ControllerContext{http: c, router: self, route_params: ParameterDictionary::new()});
    }
    fn controller<'r,T>(&'r mut self, creator: ~fn(&mut ControllerContext) -> T) -> ControllerBox<'r,T>
    {
        ControllerBox{
            router: self,
            path: ~"",
            creator: Some(creator)
        }
    }
}

struct ControllerContext<'self>
{
    http: &'self mut HttpContext,
    router: &'self Router,
    route_params: ParameterDictionary
}

trait HttpController{

}

struct ControllerBox<'self,T>{
    router: &'self mut Router,
    path: ~str,
    creator: Option<~fn(&mut ControllerContext) -> T>
}

impl<'self,T> ControllerBox<'self,T>{
    fn handles(&'self mut self, path: ~str) -> &'self mut ControllerBox<'self,T>{
        self.path=path;
        self
    }
    fn with(&'self mut self, invoker: ~fn(&mut T, &mut ControllerContext)) -> &'self mut ControllerBox<'self,T>{
        let tmp=self.creator.take();

        self.router.add(~Route{matcher: ~SimplePattern::new(self.path) as ~PatternMatcher, handler:
         |c| {
            match tmp {
                None => (),
                Some(ref t) => {
                    let mut ctrl=(*t)(c);
                    invoker(&mut ctrl, c);
                }
            };
        }});
        self
    }
}
/*
struct Meh{
    biz: ~fn(int) -> int
}

impl Meh{
    fn foo(@mut self
}
*/

struct TestController;

impl TestController{
    fn new() -> TestController{
    TestController
    }
    fn index(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str("test index");
    }
}

fn default_handler(context: &mut ControllerContext){
    context.http.response.body.push_str("404 not found");
}

fn index(context: &mut ControllerContext){
    context.http.response.body.push_str("yay index");
}

fn foo(context: &mut ControllerContext){
    context.http.response.body.push_str("yay foo");
}

fn main() {
    let mut context=HttpContext::create();
    let mut router=Router::new();
    {
        let mut test = router.controller(|_| TestController::new());
        test.handles(~"/test").with(|c,ctx| c.index(ctx));
    }

    router.execute(&mut context); //possible borrowing more than once

    println(context.response.contenttype);
    println("");
    println(context.response.body);
}<commit_msg>Fleshed out example more and cleaned some of the code up<commit_after>use std::os::getenv;
use std::rc::RcMut;

use simplepattern::ParameterDictionary;
use simplepattern::SimplePattern;
use simplepattern::PatternMatcher;

pub mod simplepattern;
struct HttpContext{
    request: Request,
    response: Response,
}

impl HttpContext{
    fn create() -> HttpContext{
        HttpContext{
            request: Request::populate(),
            response: Response::new()
        }
    }
}

struct Request {
    path: ~str,
    querystring: ~str
}

impl Request {
    fn populate() -> Request {
        Request{
            path: getenv("PATH_INFO").unwrap_or(~""),
            querystring: getenv("QUERY_STRING").unwrap_or(~"")
        }
    }
}

struct Response{
    contenttype: ~str,
    body: ~str
}

impl Response{
    fn new() -> Response{
        Response{contenttype: ~"text/plain", body: ~""}
    }
}

struct Route {
    matcher: ~PatternMatcher,
    handler: ~fn(&mut ControllerContext)
}

struct Router{
    routes: ~[Route],
}

impl Router{
    fn new() -> Router{
        Router{routes: ~[]}
    }
    fn add(&mut self, r: ~Route){
        self.routes.push(*r);
    }
    fn execute(&mut self, c: &mut HttpContext) {
        for route in self.routes.iter(){
            let res=route.matcher.matches(c.request.path);

            if(res.is_match){
                (route.handler)(&mut ControllerContext{http: c, router: self, route_params: res.params});
                return;
            }
        }
        default_handler(&mut ControllerContext{http: c, router: self, route_params: ParameterDictionary::new()});
    }
    fn controller<'r,T>(&'r mut self, creator: ~fn(&mut ControllerContext) -> T) -> ControllerBox<'r,T>
    {
        ControllerBox{
            router: self,
            path: ~"",
            creator: Some(creator)
        }
    }
}

struct ControllerContext<'self>
{
    http: &'self mut HttpContext,
    router: &'self Router,
    route_params: ParameterDictionary
}

trait HttpController{

}

struct ControllerBox<'self,T>{
    router: &'self mut Router,
    path: ~str,
    creator: Option<~fn(&mut ControllerContext) -> T>
}

impl<'self,T> ControllerBox<'self,T>{
    fn handles(&'self mut self, path: ~str) -> &'self mut ControllerBox<'self,T>{
        self.path=path;
        self
    }
    fn with(&'self mut self, invoker: ~fn(&mut T, &mut ControllerContext)) -> &'self mut ControllerBox<'self,T>{
        let tmp=self.creator.take();

        self.router.add(~Route{matcher: ~SimplePattern::new(self.path) as ~PatternMatcher, handler:
         |c| {
            match tmp {
                None => (),
                Some(ref t) => {
                    let mut ctrl=(*t)(c);
                    invoker(&mut ctrl, c);
                }
            };
        }});
        self
    }
}
/*
struct Meh{
    biz: ~fn(int) -> int
}

impl Meh{
    fn foo(@mut self
}
*/

struct TestController;

impl TestController{
    fn new() -> TestController{
    TestController
    }
    fn index(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str("test index");
    }
    fn say(&mut self, context: &mut ControllerContext) {
        context.http.response.body.push_str(context.route_params[~"message"]);
    }
}

fn default_handler(context: &mut ControllerContext){
    context.http.response.body.push_str("404 not found");
}

fn main() {
    let mut context=HttpContext::create();
    let mut router=Router::new();
    {
        let mut test = router.controller(|_| TestController::new());
        test.handles(~"/test").with(|c,ctx| c.index(ctx));
    }
    {
        let mut test = router.controller(|_| TestController::new());
        test.handles(~"/say/[message]").with(|c,ctx| c.say(ctx));
    }

    router.execute(&mut context); //possible borrowing more than once

    println(context.response.contenttype);
    println("");
    println(context.response.body);
}<|endoftext|>


<commit_before>#![feature(rustc_private)]

extern crate env_logger;
extern crate rustc_ast;
extern crate rustc_span;

use std::cell::RefCell;
use std::collections::BTreeMap;
use std::env;
use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::path::PathBuf;

use rustc_span::edition::DEFAULT_EDITION;

use rustdoc::html::markdown::{ErrorCodes, IdMap, Markdown, Playground};

pub struct ErrorMetadata {
    pub description: Option<String>,
}

/// Mapping from error codes to metadata that can be (de)serialized.
pub type ErrorMetadataMap = BTreeMap<String, ErrorMetadata>;

enum OutputFormat {
    HTML(HTMLFormatter),
    Markdown(MarkdownFormatter),
    Unknown(String),
}

impl OutputFormat {
    fn from(format: &str, resource_suffix: &str) -> OutputFormat {
        match &*format.to_lowercase() {
            "html" => OutputFormat::HTML(HTMLFormatter(
                RefCell::new(IdMap::new()),
                resource_suffix.to_owned(),
            )),
            "markdown" => OutputFormat::Markdown(MarkdownFormatter),
            s => OutputFormat::Unknown(s.to_owned()),
        }
    }
}

trait Formatter {
    fn header(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>>;
    fn title(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>>;
    fn error_code_block(
        &self,
        output: &mut dyn Write,
        info: &ErrorMetadata,
        err_code: &str,
    ) -> Result<(), Box<dyn Error>>;
    fn footer(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>>;
}

struct HTMLFormatter(RefCell<IdMap>, String);
struct MarkdownFormatter;

impl Formatter for HTMLFormatter {
    fn header(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        write!(
            output,
            r##"<!DOCTYPE html>

<title>Rust Compiler Error Index</title>
<meta charset="utf-8">

<link rel="stylesheet" type="text/css" href="light{suffix}.css"/>
<link rel="stylesheet" type="text/css" href="rust.css"/>

"##,
            suffix = self.1
        )?;
        Ok(())
    }

    fn title(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        write!(output, "
Rust Compiler Error Index
\n")?;
        Ok(())
    }

    fn error_code_block(
        &self,
        output: &mut dyn Write,
        info: &ErrorMetadata,
        err_code: &str,
    ) -> Result<(), Box<dyn Error>> {
        // Enclose each error in a div so they can be shown/hidden en masse.
        let desc_desc = match info.description {
            Some(_) => "error-described",
            None => "error-undescribed",
        };
        write!(output, "
", desc_desc)?;

        // Error title (with self-link).
        write!(
            output,
            "
{0}
\n",
            err_code
        )?;

        // Description rendered as markdown.
        match info.description {
            Some(ref desc) => {
                let mut id_map = self.0.borrow_mut();
                let playground = Playground {
                    crate_name: None,
                    url: String::from("https://play.rust-lang.org/"),
                };
                write!(
                    output,
                    "{}",
                    Markdown(
                        desc,
                        &[],
                        &mut id_map,
                        ErrorCodes::Yes,
                        DEFAULT_EDITION,
                        &Some(playground)
                    )
                    .into_string()
                )?
            }
            None => write!(output, "
No description.
\n")?,
        }

        write!(output, "
\n")?;
        Ok(())
    }

    fn footer(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        write!(
            output,
            r##"

"##
        )?;
        Ok(())
    }
}

impl Formatter for MarkdownFormatter {
    #[allow(unused_variables)]
    fn header(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        Ok(())
    }

    fn title(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        write!(output, "# Rust Compiler Error Index\n")?;
        Ok(())
    }

    fn error_code_block(
        &self,
        output: &mut dyn Write,
        info: &ErrorMetadata,
        err_code: &str,
    ) -> Result<(), Box<dyn Error>> {
        Ok(match info.description {
            Some(ref desc) => write!(output, "## {}\n{}\n", err_code, desc)?,
            None => (),
        })
    }

    #[allow(unused_variables)]
    fn footer(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        Ok(())
    }
}

/// Output an HTML page for the errors in `err_map` to `output_path`.
fn render_error_page<T: Formatter>(
    err_map: &ErrorMetadataMap,
    output_path: &Path,
    formatter: T,
) -> Result<(), Box<dyn Error>> {
    let mut output_file = File::create(output_path)?;

    formatter.header(&mut output_file)?;
    formatter.title(&mut output_file)?;

    for (err_code, info) in err_map {
        formatter.error_code_block(&mut output_file, info, err_code)?;
    }

    formatter.footer(&mut output_file)
}

fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box<dyn Error>> {
    let long_codes = register_all();
    let mut err_map = BTreeMap::new();
    for (code, desc) in long_codes {
        err_map.insert(code.to_string(), ErrorMetadata { description: desc.map(String::from) });
    }
    match format {
        OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
        OutputFormat::HTML(h) => render_error_page(&err_map, dst, h)?,
        OutputFormat::Markdown(m) => render_error_page(&err_map, dst, m)?,
    }
    Ok(())
}

fn parse_args() -> (OutputFormat, PathBuf) {
    let mut args = env::args().skip(1);
    let format = args.next();
    let dst = args.next();
    let resource_suffix = args.next().unwrap_or_else(String::new);
    let format = format
        .map(|a| OutputFormat::from(&a, &resource_suffix))
        .unwrap_or(OutputFormat::from("html", &resource_suffix));
    let dst = dst.map(PathBuf::from).unwrap_or_else(|| match format {
        OutputFormat::HTML(..) => PathBuf::from("doc/error-index.html"),
        OutputFormat::Markdown(..) => PathBuf::from("doc/error-index.md"),
        OutputFormat::Unknown(..) => PathBuf::from("<nul>"),
    });
    (format, dst)
}

fn main() {
    env_logger::init();
    let (format, dst) = parse_args();
    let result = rustc_ast::with_default_session_globals(move || main_with_result(format, &dst));
    if let Err(e) = result {
        panic!("{}", e.to_string());
    }
}

include!(concat!(env!("OUT_DIR"), "/error_codes.rs"));
<commit_msg>Update error index generator to tracing<commit_after>#![feature(rustc_private)]

extern crate rustc_ast;
extern crate rustc_driver;
extern crate rustc_span;

use std::cell::RefCell;
use std::collections::BTreeMap;
use std::env;
use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::path::PathBuf;

use rustc_span::edition::DEFAULT_EDITION;

use rustdoc::html::markdown::{ErrorCodes, IdMap, Markdown, Playground};

pub struct ErrorMetadata {
    pub description: Option<String>,
}

/// Mapping from error codes to metadata that can be (de)serialized.
pub type ErrorMetadataMap = BTreeMap<String, ErrorMetadata>;

enum OutputFormat {
    HTML(HTMLFormatter),
    Markdown(MarkdownFormatter),
    Unknown(String),
}

impl OutputFormat {
    fn from(format: &str, resource_suffix: &str) -> OutputFormat {
        match &*format.to_lowercase() {
            "html" => OutputFormat::HTML(HTMLFormatter(
                RefCell::new(IdMap::new()),
                resource_suffix.to_owned(),
            )),
            "markdown" => OutputFormat::Markdown(MarkdownFormatter),
            s => OutputFormat::Unknown(s.to_owned()),
        }
    }
}

trait Formatter {
    fn header(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>>;
    fn title(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>>;
    fn error_code_block(
        &self,
        output: &mut dyn Write,
        info: &ErrorMetadata,
        err_code: &str,
    ) -> Result<(), Box<dyn Error>>;
    fn footer(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>>;
}

struct HTMLFormatter(RefCell<IdMap>, String);
struct MarkdownFormatter;

impl Formatter for HTMLFormatter {
    fn header(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        write!(
            output,
            r##"<!DOCTYPE html>

<title>Rust Compiler Error Index</title>
<meta charset="utf-8">

<link rel="stylesheet" type="text/css" href="light{suffix}.css"/>
<link rel="stylesheet" type="text/css" href="rust.css"/>

"##,
            suffix = self.1
        )?;
        Ok(())
    }

    fn title(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        write!(output, "
Rust Compiler Error Index
\n")?;
        Ok(())
    }

    fn error_code_block(
        &self,
        output: &mut dyn Write,
        info: &ErrorMetadata,
        err_code: &str,
    ) -> Result<(), Box<dyn Error>> {
        // Enclose each error in a div so they can be shown/hidden en masse.
        let desc_desc = match info.description {
            Some(_) => "error-described",
            None => "error-undescribed",
        };
        write!(output, "
", desc_desc)?;

        // Error title (with self-link).
        write!(
            output,
            "
{0}
\n",
            err_code
        )?;

        // Description rendered as markdown.
        match info.description {
            Some(ref desc) => {
                let mut id_map = self.0.borrow_mut();
                let playground = Playground {
                    crate_name: None,
                    url: String::from("https://play.rust-lang.org/"),
                };
                write!(
                    output,
                    "{}",
                    Markdown(
                        desc,
                        &[],
                        &mut id_map,
                        ErrorCodes::Yes,
                        DEFAULT_EDITION,
                        &Some(playground)
                    )
                    .into_string()
                )?
            }
            None => write!(output, "
No description.
\n")?,
        }

        write!(output, "
\n")?;
        Ok(())
    }

    fn footer(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        write!(
            output,
            r##"

"##
        )?;
        Ok(())
    }
}

impl Formatter for MarkdownFormatter {
    #[allow(unused_variables)]
    fn header(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        Ok(())
    }

    fn title(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        write!(output, "# Rust Compiler Error Index\n")?;
        Ok(())
    }

    fn error_code_block(
        &self,
        output: &mut dyn Write,
        info: &ErrorMetadata,
        err_code: &str,
    ) -> Result<(), Box<dyn Error>> {
        Ok(match info.description {
            Some(ref desc) => write!(output, "## {}\n{}\n", err_code, desc)?,
            None => (),
        })
    }

    #[allow(unused_variables)]
    fn footer(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
        Ok(())
    }
}

/// Output an HTML page for the errors in `err_map` to `output_path`.
fn render_error_page<T: Formatter>(
    err_map: &ErrorMetadataMap,
    output_path: &Path,
    formatter: T,
) -> Result<(), Box<dyn Error>> {
    let mut output_file = File::create(output_path)?;

    formatter.header(&mut output_file)?;
    formatter.title(&mut output_file)?;

    for (err_code, info) in err_map {
        formatter.error_code_block(&mut output_file, info, err_code)?;
    }

    formatter.footer(&mut output_file)
}

fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box<dyn Error>> {
    let long_codes = register_all();
    let mut err_map = BTreeMap::new();
    for (code, desc) in long_codes {
        err_map.insert(code.to_string(), ErrorMetadata { description: desc.map(String::from) });
    }
    match format {
        OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
        OutputFormat::HTML(h) => render_error_page(&err_map, dst, h)?,
        OutputFormat::Markdown(m) => render_error_page(&err_map, dst, m)?,
    }
    Ok(())
}

fn parse_args() -> (OutputFormat, PathBuf) {
    let mut args = env::args().skip(1);
    let format = args.next();
    let dst = args.next();
    let resource_suffix = args.next().unwrap_or_else(String::new);
    let format = format
        .map(|a| OutputFormat::from(&a, &resource_suffix))
        .unwrap_or(OutputFormat::from("html", &resource_suffix));
    let dst = dst.map(PathBuf::from).unwrap_or_else(|| match format {
        OutputFormat::HTML(..) => PathBuf::from("doc/error-index.html"),
        OutputFormat::Markdown(..) => PathBuf::from("doc/error-index.md"),
        OutputFormat::Unknown(..) => PathBuf::from("<nul>"),
    });
    (format, dst)
}

fn main() {
    rustc_driver::init_env_logger("RUST_LOG");
    let (format, dst) = parse_args();
    let result = rustc_ast::with_default_session_globals(move || main_with_result(format, &dst));
    if let Err(e) = result {
        panic!("{}", e.to_string());
    }
}

include!(concat!(env!("OUT_DIR"), "/error_codes.rs"));
<|endoftext|>


<commit_before>pub struct Def {
    pub name: &'static str,
    pub code: &'static [u8],
}

macro_rules! defs {
    ($($defs:ident, $def:ident = $name:expr, $path:expr;)*) => ($(
        const $def: Def = Def { name: $name, code: include_bytes!($path) };
        const $defs: &'static [Def] = &[$def];
    )*);
}

defs! {
    LUA51_BASE_DEFS,    LUA51_BASE_DEF    = "lua51_base",    "defs/lua51_base.lua";
    LUA51_PACKAGE_DEFS, LUA51_PACKAGE_DEF = "lua51_package", "defs/lua51_package.lua";
    LUA51_STRING_DEFS,  LUA51_STRING_DEF  = "lua51_string",  "defs/lua51_string.lua";
    LUA51_TABLE_DEFS,   LUA51_TABLE_DEF   = "lua51_table",   "defs/lua51_table.lua";
    LUA51_MATH_DEFS,    LUA51_MATH_DEF    = "lua51_math",    "defs/lua51_math.lua";
    LUA51_IO_DEFS,      LUA51_IO_DEF      = "lua51_io",      "defs/lua51_io.lua";
    LUA51_DEBUG_DEFS,   LUA51_DEBUG_DEF   = "lua51_debug",   "defs/lua51_debug.lua";
}

const LUA51_DEFS: &'static [Def] = &[
    LUA51_BASE_DEF,
    LUA51_PACKAGE_DEF,
    LUA51_STRING_DEF,
    LUA51_TABLE_DEF,
    LUA51_MATH_DEF,
    LUA51_IO_DEF,
    LUA51_DEBUG_DEF,
];

pub fn get_defs(name: &str) -> Option<&'static [Def]> {
    match name {
        "lua51"         => Some(LUA51_DEFS),
        "lua51_base"    => Some(LUA51_BASE_DEFS),
        "lua51_package" => Some(LUA51_PACKAGE_DEFS),
        "lua51_string"  => Some(LUA51_STRING_DEFS),
        "lua51_table"   => Some(LUA51_TABLE_DEFS),
        "lua51_math"    => Some(LUA51_MATH_DEFS),
        "lua51_io"      => Some(LUA51_IO_DEFS),
        "lua51_debug"   => Some(LUA51_DEBUG_DEFS),
        _ => None,
    }
}

<commit_msg>added missing lua51_os definition (duh).<commit_after>pub struct Def {
    pub name: &'static str,
    pub code: &'static [u8],
}

macro_rules! defs {
    ($($defs:ident, $def:ident = $name:expr, $path:expr;)*) => ($(
        const $def: Def = Def { name: $name, code: include_bytes!($path) };
        const $defs: &'static [Def] = &[$def];
    )*);
}

defs! {
    LUA51_BASE_DEFS,    LUA51_BASE_DEF    = "lua51_base",    "defs/lua51_base.lua";
    LUA51_PACKAGE_DEFS, LUA51_PACKAGE_DEF = "lua51_package", "defs/lua51_package.lua";
    LUA51_STRING_DEFS,  LUA51_STRING_DEF  = "lua51_string",  "defs/lua51_string.lua";
    LUA51_TABLE_DEFS,   LUA51_TABLE_DEF   = "lua51_table",   "defs/lua51_table.lua";
    LUA51_MATH_DEFS,    LUA51_MATH_DEF    = "lua51_math",    "defs/lua51_math.lua";
    LUA51_IO_DEFS,      LUA51_IO_DEF      = "lua51_io",      "defs/lua51_io.lua";
    LUA51_OS_DEFS,      LUA51_OS_DEF      = "lua51_os",      "defs/lua51_os.lua";
    LUA51_DEBUG_DEFS,   LUA51_DEBUG_DEF   = "lua51_debug",   "defs/lua51_debug.lua";
}

const LUA51_DEFS: &'static [Def] = &[
    LUA51_BASE_DEF,
    LUA51_PACKAGE_DEF,
    LUA51_STRING_DEF,
    LUA51_TABLE_DEF,
    LUA51_MATH_DEF,
    LUA51_IO_DEF,
    LUA51_OS_DEF,
    LUA51_DEBUG_DEF,
];

pub fn get_defs(name: &str) -> Option<&'static [Def]> {
    match name {
        "lua51"         => Some(LUA51_DEFS),
        "lua51_base"    => Some(LUA51_BASE_DEFS),
        "lua51_package" => Some(LUA51_PACKAGE_DEFS),
        "lua51_string"  => Some(LUA51_STRING_DEFS),
        "lua51_table"   => Some(LUA51_TABLE_DEFS),
        "lua51_math"    => Some(LUA51_MATH_DEFS),
        "lua51_io"      => Some(LUA51_IO_DEFS),
        "lua51_os"      => Some(LUA51_OS_DEFS),
        "lua51_debug"   => Some(LUA51_DEBUG_DEFS),
        _ => None,
    }
}

<|endoftext|>


<commit_before>use context::base::BaseContextBuilder;
use super::{
    CONTEXT_NAME,
    CONTEXT_UUID,
    MessageAction,
};

use action::Action;
use conditions::ConditionsBuilder;
use config;
use dispatcher::Response;
use dispatcher::response::ResponseSender;
use state::State;

use handlebars::Template;
use std::cell::RefCell;
use std::rc::Rc;
use uuid::Uuid;

struct DummyResponseSender {
    responses: Rc<RefCell<Vec<Response>>>
}

impl ResponseSender<Response> for DummyResponseSender {
    fn send_response(&mut self, response: Response) {
        self.responses.borrow_mut().push(response);
    }
}

#[test]
fn test_given_a_message_action_when_it_is_executed_then_it_adds_the_name_and_uuid_of_the_context_to_the_message() {
    let name = Some("name".to_string());
    let base_context = {
        let conditions = ConditionsBuilder::new(100).build();
        let uuid = Uuid::new_v4();
        BaseContextBuilder::new(uuid, conditions).name(name.clone()).build()
    };
    let state = State::new();
    let responses = Rc::new(RefCell::new(Vec::new()));
    let message_action = {
        let response_sender = DummyResponseSender {responses: responses.clone()};
        let message = Template::compile("message".to_string()).ok().expect("Failed to compile a handlebars template");
        let config_action = config::action::message::MessageActionBuilder::new("uuid", message).build();
        MessageAction::new(
            Rc::new(RefCell::new(Box::new(response_sender))),
            config_action
        )
    };

    message_action.execute(&state, &base_context);
    assert_eq!(1, responses.borrow().len());
    let responses = responses.borrow();
    if let &Response::Message(ref response) = responses.get(0).unwrap() {
        assert_eq!(name.as_ref().unwrap(), response.message().get(CONTEXT_NAME).unwrap());
        assert_eq!(&base_context.uuid().to_hyphenated_string(), response.message().get(CONTEXT_UUID).unwrap());
    } else {
        unreachable!();
    }
}
<commit_msg>tests: add a message template rendering test<commit_after>use context::base::BaseContextBuilder;
use super::{
    CONTEXT_LEN,
    CONTEXT_NAME,
    CONTEXT_UUID,
    MessageAction,
};

use action::Action;
use conditions::ConditionsBuilder;
use config;
use dispatcher::Response;
use dispatcher::response::ResponseSender;
use message::MessageBuilder;
use state::State;

use env_logger;
use handlebars::Template;
use std::cell::RefCell;
use std::rc::Rc;
use uuid::Uuid;

struct DummyResponseSender {
    responses: Rc<RefCell<Vec<Response>>>
}

impl ResponseSender<Response> for DummyResponseSender {
    fn send_response(&mut self, response: Response) {
        self.responses.borrow_mut().push(response);
    }
}

#[test]
fn test_given_a_message_action_when_it_is_executed_then_it_adds_the_name_and_uuid_of_the_context_to_the_message() {
    let name = Some("name".to_string());
    let base_context = {
        let conditions = ConditionsBuilder::new(100).build();
        let uuid = Uuid::new_v4();
        BaseContextBuilder::new(uuid, conditions).name(name.clone()).build()
    };
    let state = State::new();
    let responses = Rc::new(RefCell::new(Vec::new()));
    let message_action = {
        let response_sender = DummyResponseSender {responses: responses.clone()};
        let message = Template::compile("message".to_string()).ok().expect("Failed to compile a handlebars template");
        let config_action = config::action::message::MessageActionBuilder::new("uuid", message).build();
        MessageAction::new(
            Rc::new(RefCell::new(Box::new(response_sender))),
            config_action
        )
    };

    message_action.execute(&state, &base_context);
    assert_eq!(1, responses.borrow().len());
    let responses = responses.borrow();
    if let &Response::Message(ref response) = responses.get(0).unwrap() {
        assert_eq!(name.as_ref().unwrap(), response.message().get(CONTEXT_NAME).unwrap());
        assert_eq!(&base_context.uuid().to_hyphenated_string(), response.message().get(CONTEXT_UUID).unwrap());
        assert_eq!("0", response.message().get(CONTEXT_LEN).unwrap());
    } else {
        unreachable!();
    }
}

#[test]
fn test_given_message_action_when_it_is_executed_then_it_uses_the_messages_to_render_the_message_and_additonal_templated_values() {
    let _ = env_logger::init();
    let name = Some("name".to_string());
    let base_context = {
        let conditions = ConditionsBuilder::new(100).build();
        let uuid = Uuid::new_v4();
        BaseContextBuilder::new(uuid, conditions).name(name.clone()).build()
    };
    let state = {
        let mut state = State::new();
        state.add_message(Rc::new(MessageBuilder::new("uuid1", "message1").pair("key1", "value1").build()));
        state.add_message(Rc::new(MessageBuilder::new("uuid2", "message2").pair("key2", "value2").build()));
        state
    };
    let responses = Rc::new(RefCell::new(Vec::new()));
    let message_action = {
        let response_sender = DummyResponseSender {responses: responses.clone()};
        let message = Template::compile("key1={{{messages.[0].values.key1}}} key2={{{messages.[1].values.key2}}}".to_string()).ok().expect("Failed to compile a handlebars template");
        let config_action = config::action::message::MessageActionBuilder::new("uuid", message)
                                .pair("message_num", Template::compile("we have {{context_len}} messages".to_string()).ok().expect("Failed to compile a handlebars template"))
                                .build();
        MessageAction::new(
            Rc::new(RefCell::new(Box::new(response_sender))),
            config_action
        )
    };

    message_action.execute(&state, &base_context);
    assert_eq!(1, responses.borrow().len());
    let responses = responses.borrow();
    if let &Response::Message(ref response) = responses.get(0).unwrap() {
        assert_eq!(name.as_ref().unwrap(), response.message().get(CONTEXT_NAME).unwrap());
        assert_eq!(&base_context.uuid().to_hyphenated_string(), response.message().get(CONTEXT_UUID).unwrap());
        let message = response.message();
        assert_eq!("we have 2 messages", message.get("message_num").expect("Failed to get an inserted key from a map"));
        assert_eq!("key1=value1 key2=value2", message.message());
    } else {
        unreachable!();
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Averages/Mean_angle

use std::num::Float;

fn mean_angle(angles: &[f64]) -> f64 {
    let mean_cos = angles.iter().map(|&x| (x * Float::pi() / 180.).cos())
                                .fold(0., |a, b| a + b) / (angles.len() as f64);
    let mean_sin = angles.iter().map(|&x| (x * Float::pi() / 180.).sin())
                                .fold(0., |a, b| a + b) / (angles.len() as f64);

    mean_sin.atan2(mean_cos) * 180. / Float::pi()
}

#[cfg(not(test))]
fn main() {
    let set1 = [350., 10.];
    let set2 = [90., 180., 270., 360.];
    let set3 = [10., 20., 30.];

    println!("Mean angle of first set is {} degrees", mean_angle(set1));
    println!("Mean angle of second set is {} degrees", mean_angle(set2));
    println!("Mean angle of third set is {} degrees", mean_angle(set3));
}

#[test]
fn basic_tests() {
    let set1 = [350., 10.];
    let set2 = [90., 180., 270., 360.];
    let set3 = [10., 20., 30.];

    // We need to round the numbers
    assert!(mean_angle(set1).round() == 0.);
    assert!(mean_angle(set2).round() == -90.);
    assert!(mean_angle(set3).round() == 20.);
}
<commit_msg>averages mean angle: Efficiency + style<commit_after>// Implements http://rosettacode.org/wiki/Averages/Mean_angle

use std::num::Float;

fn mean_angle(angles: &[f64]) -> f64 {
    let (sum_cos, sum_sin) = angles.iter()
                                   .map(|&x| x * Float::pi() / 180.)
                                   // We map into a tuple of sin and cos so we
                                   // only need to iterate the slice once.
                                   .map(|x| (x.cos(), x.sin()))
                                   .fold((0., 0.),
                                        |(sc, ss), (c, s)| (sc + c, ss + s));

    let mean_cos = sum_cos / angles.len() as f64;
    let mean_sin = sum_sin / angles.len() as f64;

    mean_sin.atan2(mean_cos) * 180. / Float::pi()
}

#[cfg(not(test))]
fn main() {
    let set1 = [350., 10.];
    let set2 = [90., 180., 270., 360.];
    let set3 = [10., 20., 30.];

    println!("Mean angle of first set is {} degrees", mean_angle(set1));
    println!("Mean angle of second set is {} degrees", mean_angle(set2));
    println!("Mean angle of third set is {} degrees", mean_angle(set3));
}

#[test]
fn basic_tests() {
    let set1 = [350., 10.];
    let set2 = [90., 180., 270., 360.];
    let set3 = [10., 20., 30.];

    // We need to round the numbers
    assert_eq!(mean_angle(set1).round(), 0.);
    assert_eq!(mean_angle(set2).round(), -90.);
    assert_eq!(mean_angle(set3).round(), 20.);
}
<|endoftext|>