<commit_before>use helpers::*;
use core::mem;
use hil::{uart, Controller};
use hil::uart::Parity;
use dma::{DMAChannel, DMAClient, DMAPeripheral};
use nvic;
use pm::{self, Clock, PBAClock};
use chip;

#[repr(C, packed)]
struct Registers {
    cr: u32,
    mr: u32,
    ier: u32,
    idr: u32,
    imr: u32,
    csr: u32,
    rhr: u32,
    thr: u32,
    brgr: u32, // 0x20
    rtor: u32,
    ttgr: u32,
    reserved0: [u32; 5],
    fidi: u32, // 0x40
    ner: u32,
    reserved1: u32,
    ifr: u32,
    man: u32,
    linmr: u32,
    linir: u32,
    linbrr: u32,
    wpmr: u32,
    wpsr: u32,
    version: u32
}

const SIZE: usize = 0x4000;
const BASE_ADDRESS: usize = 0x40024000;

#[derive(Copy,Clone)]
pub enum Location {
    USART0, USART1, USART2, USART3
}

pub struct USART {
    regs: *mut Registers,
    client: Option<&'static uart::Client>,
    clock: Clock,
    nvic: nvic::NvicIdx,
    dma_peripheral: DMAPeripheral,
    dma: Option<&'static mut DMAChannel>,
}

pub struct USARTParams {
    //pub client: &'static Shared<uart::Client>,
    pub baud_rate: u32,
    pub data_bits: u8,
    pub parity: Parity
}

impl Controller for USART {
    type Config = USARTParams;

    fn configure(&self, params: USARTParams) {
     //   self.client = Some(params.client.borrow_mut());
        let chrl = ((params.data_bits - 1) & 0x3) as u32;
        let mode = 0 /* mode */
            | 0 << 4 /*USCLKS*/
            | chrl << 6 /* Character Length */
            | (params.parity as u32) << 9 /* Parity */
            | 0 << 12 /* Number of stop bits = 1 */
            | 1 << 19 /* Oversample at 8 times baud rate */;

        self.enable_clock();
        self.set_baud_rate(params.baud_rate);
        self.set_mode(mode);
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.ttgr, 4);
        self.enable_rx_interrupts();
    }
}

pub static mut USART0 : USART =
    USART::new(Location::USART0, PBAClock::USART0, nvic::NvicIdx::USART0);
pub static mut USART1 : USART =
    USART::new(Location::USART1, PBAClock::USART1, nvic::NvicIdx::USART1);
pub static mut USART2 : USART =
    USART::new(Location::USART2, PBAClock::USART2, nvic::NvicIdx::USART2);
pub static mut USART3 : USART =
    USART::new(Location::USART3, PBAClock::USART3, nvic::NvicIdx::USART3);

impl USART {
    const fn new(location: Location, clock: PBAClock, nvic: nvic::NvicIdx)
            -> USART {
        USART {
            regs: (BASE_ADDRESS + (location as usize) * SIZE)
                as *mut Registers,
            clock: Clock::PBA(clock),
            nvic: nvic,
            dma: None,
            dma_peripheral: DMAPeripheral::USART0_RX, // Set to some default.
                                                      // This is updated when a
                                                      // real DMA is configured.
            client: None,
        }
    }

    pub fn set_client<C: uart::Client>(&mut self, client: &'static C) {
        self.client = Some(client);
    }

    pub fn set_dma(&mut self, dma: &'static mut DMAChannel, dma_peripheral: DMAPeripheral) {
        self.dma = Some(dma);
        self.dma_peripheral = dma_peripheral;
    }

    fn set_baud_rate(&self, baud_rate: u32) {
        let cd = 48000000 / (8 * baud_rate);
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.brgr, cd);
    }

    fn set_mode(&self, mode: u32) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.mr, mode);
    }

    fn enable_clock(&self) {
        unsafe {
            pm::enable_clock(self.clock);
        }
    }

    fn enable_nvic(&self) {
        unsafe {
            nvic::enable(self.nvic);
        }
    }

    fn disable_nvic(&self) {
        unsafe {
            nvic::disable(self.nvic);
        }
    }

    pub fn enable_rx_interrupts(&self) {
        self.enable_nvic();
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.ier, 1 as u32);
    }

    pub fn enable_tx_interrupts(&mut self) {
        self.enable_nvic();
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.ier, 2 as u32);
    }

    pub fn disable_rx_interrupts(&mut self) {
        self.disable_nvic();
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.idr, 1 as u32);
    }

    pub fn handle_interrupt(&mut self) {
        use hil::uart::UART;
        if self.rx_ready() {
            let regs : &Registers = unsafe { mem::transmute(self.regs) };
            let c = volatile_load(&regs.rhr) as u8;
            match self.client {
                Some(ref client) => {client.read_done(c)},
                None => {}
            }
        }
    }

    pub fn reset_rx(&mut self) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.cr, 1 << 2);
    }
}

impl DMAClient for USART {
    fn xfer_done(&mut self, _pid: usize) {
        let buffer = match self.dma.as_mut() {
            Some(dma) => {
                let buf = dma.abort_xfer();
                dma.disable();
                buf
            },
            None => None
        };
        self.client.as_ref().map(move |c| {
            buffer.map(|buf| c.write_done(buf));
        });
    }
}

impl uart::UART for USART {
    fn init(&mut self, params: uart::UARTParams) {
        let chrl = ((params.data_bits - 1) & 0x3) as u32;
        let mode = 0 /* mode */
            | 0 << 4 /*USCLKS*/
            | chrl << 6 /* Character Length */
            | (params.parity as u32) << 9 /* Parity */
            | 0 << 12 /* Number of stop bits = 1 */
            | 1 << 19 /* Oversample at 8 times baud rate */;

        self.enable_clock();
        self.set_baud_rate(params.baud_rate);
        self.set_mode(mode);
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.ttgr, 4);
    }

    fn send_byte(&self, byte: u8) {
        while !self.tx_ready() {}
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.thr, byte as u32);
    }

    fn send_bytes(&self, bytes: &'static mut [u8], len: usize) {
        // TODO: Verify that this is the best way to do this. I just needed
        //       to find some way to tell the compiler to chill out.
        let local_periph = self.dma_peripheral.clone();
        self.dma.as_ref().map(move |dma| {
            dma.enable();
            dma.do_xfer(local_periph, bytes, len);
        });
    }

    fn rx_ready(&self) -> bool {
        let regs : &Registers = unsafe { mem::transmute(self.regs) };
        volatile_load(&regs.csr) & 0b1 != 0
    }

    fn tx_ready(&self) -> bool {
        let regs : &Registers = unsafe { mem::transmute(self.regs) };
        volatile_load(&regs.csr) & 0b10 != 0
    }

    fn read_byte(&self) -> u8 {
        while !self.rx_ready() {}
        let regs : &Registers = unsafe { mem::transmute(self.regs) };
        volatile_load(&regs.rhr) as u8
    }

    fn enable_rx(&self) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.cr, 1 << 4);
    }

    fn disable_rx(&mut self) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.cr, 1 << 5);
    }

    fn enable_tx(&self) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.cr, 1 << 6);
    }

    fn disable_tx(&mut self) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.cr, 1 << 7);
    }

}

#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern fn USART2_Handler() {
    use common::Queue;

    nvic::disable(nvic::NvicIdx::USART2);
    chip::INTERRUPT_QUEUE.as_mut().unwrap().enqueue(nvic::NvicIdx::USART2);
}

#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern fn USART3_Handler() {
    use common::Queue;

    nvic::disable(nvic::NvicIdx::USART3);
    chip::INTERRUPT_QUEUE.as_mut().unwrap().enqueue(nvic::NvicIdx::USART3);
}

<commit_msg>SAM4L: Rust nit in USART<commit_after>use helpers::*;
use core::mem;
use hil::{uart, Controller};
use hil::uart::Parity;
use dma::{DMAChannel, DMAClient, DMAPeripheral};
use nvic;
use pm::{self, Clock, PBAClock};
use chip;

#[repr(C, packed)]
struct Registers {
    cr: u32,
    mr: u32,
    ier: u32,
    idr: u32,
    imr: u32,
    csr: u32,
    rhr: u32,
    thr: u32,
    brgr: u32, // 0x20
    rtor: u32,
    ttgr: u32,
    reserved0: [u32; 5],
    fidi: u32, // 0x40
    ner: u32,
    reserved1: u32,
    ifr: u32,
    man: u32,
    linmr: u32,
    linir: u32,
    linbrr: u32,
    wpmr: u32,
    wpsr: u32,
    version: u32
}

const SIZE: usize = 0x4000;
const BASE_ADDRESS: usize = 0x40024000;

#[derive(Copy,Clone)]
pub enum Location {
    USART0, USART1, USART2, USART3
}

pub struct USART {
    regs: *mut Registers,
    client: Option<&'static uart::Client>,
    clock: Clock,
    nvic: nvic::NvicIdx,
    dma_peripheral: DMAPeripheral,
    dma: Option<&'static mut DMAChannel>,
}

pub struct USARTParams {
    //pub client: &'static Shared<uart::Client>,
    pub baud_rate: u32,
    pub data_bits: u8,
    pub parity: Parity
}

impl Controller for USART {
    type Config = USARTParams;

    fn configure(&self, params: USARTParams) {
     //   self.client = Some(params.client.borrow_mut());
        let chrl = ((params.data_bits - 1) & 0x3) as u32;
        let mode = 0 /* mode */
            | 0 << 4 /*USCLKS*/
            | chrl << 6 /* Character Length */
            | (params.parity as u32) << 9 /* Parity */
            | 0 << 12 /* Number of stop bits = 1 */
            | 1 << 19 /* Oversample at 8 times baud rate */;

        self.enable_clock();
        self.set_baud_rate(params.baud_rate);
        self.set_mode(mode);
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.ttgr, 4);
        self.enable_rx_interrupts();
    }
}

pub static mut USART0 : USART =
    USART::new(Location::USART0, PBAClock::USART0, nvic::NvicIdx::USART0);
pub static mut USART1 : USART =
    USART::new(Location::USART1, PBAClock::USART1, nvic::NvicIdx::USART1);
pub static mut USART2 : USART =
    USART::new(Location::USART2, PBAClock::USART2, nvic::NvicIdx::USART2);
pub static mut USART3 : USART =
    USART::new(Location::USART3, PBAClock::USART3, nvic::NvicIdx::USART3);

impl USART {
    const fn new(location: Location, clock: PBAClock, nvic: nvic::NvicIdx)
            -> USART {
        USART {
            regs: (BASE_ADDRESS + (location as usize) * SIZE)
                as *mut Registers,
            clock: Clock::PBA(clock),
            nvic: nvic,
            dma: None,
            dma_peripheral: DMAPeripheral::USART0_RX, // Set to some default.
                                                      // This is updated when a
                                                      // real DMA is configured.
            client: None,
        }
    }

    pub fn set_client<C: uart::Client>(&mut self, client: &'static C) {
        self.client = Some(client);
    }

    pub fn set_dma(&mut self, dma: &'static mut DMAChannel, dma_peripheral: DMAPeripheral) {
        self.dma = Some(dma);
        self.dma_peripheral = dma_peripheral;
    }

    fn set_baud_rate(&self, baud_rate: u32) {
        let cd = 48000000 / (8 * baud_rate);
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.brgr, cd);
    }

    fn set_mode(&self, mode: u32) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.mr, mode);
    }

    fn enable_clock(&self) {
        unsafe {
            pm::enable_clock(self.clock);
        }
    }

    fn enable_nvic(&self) {
        unsafe {
            nvic::enable(self.nvic);
        }
    }

    fn disable_nvic(&self) {
        unsafe {
            nvic::disable(self.nvic);
        }
    }

    pub fn enable_rx_interrupts(&self) {
        self.enable_nvic();
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.ier, 1 as u32);
    }

    pub fn enable_tx_interrupts(&mut self) {
        self.enable_nvic();
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.ier, 2 as u32);
    }

    pub fn disable_rx_interrupts(&mut self) {
        self.disable_nvic();
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.idr, 1 as u32);
    }

    pub fn handle_interrupt(&mut self) {
        use hil::uart::UART;
        if self.rx_ready() {
            let regs : &Registers = unsafe { mem::transmute(self.regs) };
            let c = volatile_load(&regs.rhr) as u8;
            match self.client {
                Some(ref client) => {client.read_done(c)},
                None => {}
            }
        }
    }

    pub fn reset_rx(&mut self) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.cr, 1 << 2);
    }
}

impl DMAClient for USART {
    fn xfer_done(&mut self, _pid: usize) {
        let buffer = match self.dma.as_mut() {
            Some(dma) => {
                let buf = dma.abort_xfer();
                dma.disable();
                buf
            },
            None => None
        };
        self.client.as_ref().map(move |c| {
            buffer.map(|buf| c.write_done(buf));
        });
    }
}

impl uart::UART for USART {
    fn init(&mut self, params: uart::UARTParams) {
        let chrl = ((params.data_bits - 1) & 0x3) as u32;
        let mode = 0 /* mode */
            | 0 << 4 /*USCLKS*/
            | chrl << 6 /* Character Length */
            | (params.parity as u32) << 9 /* Parity */
            | 0 << 12 /* Number of stop bits = 1 */
            | 1 << 19 /* Oversample at 8 times baud rate */;

        self.enable_clock();
        self.set_baud_rate(params.baud_rate);
        self.set_mode(mode);
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.ttgr, 4);
    }

    fn send_byte(&self, byte: u8) {
        while !self.tx_ready() {}
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.thr, byte as u32);
    }

    fn send_bytes(&self, bytes: &'static mut [u8], len: usize) {
        self.dma.as_ref().map(move |dma| {
            dma.enable();
            dma.do_xfer(self.dma_peripheral, bytes, len);
        });
    }

    fn rx_ready(&self) -> bool {
        let regs : &Registers = unsafe { mem::transmute(self.regs) };
        volatile_load(&regs.csr) & 0b1 != 0
    }

    fn tx_ready(&self) -> bool {
        let regs : &Registers = unsafe { mem::transmute(self.regs) };
        volatile_load(&regs.csr) & 0b10 != 0
    }

    fn read_byte(&self) -> u8 {
        while !self.rx_ready() {}
        let regs : &Registers = unsafe { mem::transmute(self.regs) };
        volatile_load(&regs.rhr) as u8
    }

    fn enable_rx(&self) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.cr, 1 << 4);
    }

    fn disable_rx(&mut self) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.cr, 1 << 5);
    }

    fn enable_tx(&self) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.cr, 1 << 6);
    }

    fn disable_tx(&mut self) {
        let regs : &mut Registers = unsafe { mem::transmute(self.regs) };
        volatile_store(&mut regs.cr, 1 << 7);
    }

}

#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern fn USART2_Handler() {
    use common::Queue;

    nvic::disable(nvic::NvicIdx::USART2);
    chip::INTERRUPT_QUEUE.as_mut().unwrap().enqueue(nvic::NvicIdx::USART2);
}

#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern fn USART3_Handler() {
    use common::Queue;

    nvic::disable(nvic::NvicIdx::USART3);
    chip::INTERRUPT_QUEUE.as_mut().unwrap().enqueue(nvic::NvicIdx::USART3);
}

<|endoftext|>


<commit_before>use ast::{Ast, AstTrait};
use token::{TokenTrait, Type};

pub struct Eval {
    ast: Ast,
    stack: Vec<(Ast, usize)>,
    evaluated: bool
}

pub trait EvalTrait {
    fn eval(&mut self);
    fn is_evaluated(&self) -> bool;
}

pub trait PrettyPrint {
    fn pretty_print(&mut self) -> String;
    fn push_whitespace(&self, pretty: &mut String);
}

impl PrettyPrint for Eval {
    fn push_whitespace(&self, pretty: &mut String) {
        for _ in 0..self.stack.len() {
            pretty.push('\t');
        }
    }

    fn pretty_print(&mut self) -> String {
        let mut pretty = String::new();
        loop {
            match self.stack.pop() {
                Some(mut current) => {
                    match current.0.get_child(0) {
                        Some(mut child) => {
                            self.stack.push(current);
                            if child.node_val.is_some() {
                                let tok = child.node_val.unwrap();
                                if tok.tok_type == Type::Oparen {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('(');
                                    pretty.push('\n');
                                } else if tok.tok_type == Type::OpenList {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('<');
                                    pretty.push('\n');
                                }
                                child.node_val = Some(tok);
                            }
                            self.stack.push((child, 0));
                        },
                        None => {
                            if current.0.node_val.is_some() {
                                let tok = current.0.node_val.unwrap();
                                self.push_whitespace(&mut pretty);
                                if tok.tok_type == Type::Oparen {
                                    pretty.push(')');
                                } else if tok.tok_type == Type::OpenList {
                                    pretty.push('>');
                                } else {
                                    pretty.push_str(&tok.get_lexed());
                                }
                            }
                            pretty.push('\n');
                        }
                    }
                },
                None => {
                    match self.ast.get_child(0) {
                        Some(mut child) => {
                            if child.node_val.is_some() {
                                let tok = child.node_val.unwrap();
                                if tok.tok_type == Type::Oparen {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('(');
                                    pretty.push('\n');
                                } else if tok.tok_type == Type::OpenList {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('<');
                                    pretty.push('\n');
                                }
                                child.node_val = Some(tok);
                            }
                            self.stack.push((child, 0));
                        },
                        None => break
                    }
                }
            }
            if self.stack.is_empty() && self.ast.child_count() == 0 {
                break;
            }
        }
        pretty
    }
}

impl EvalTrait for Eval {
    fn eval(&mut self) {
        let mut scope = Scope::new_root();
        while !self.evaluated {
            scope = self.eval_node(scope); // If scope says evaluate, evaluate.
        }
    }

    fn is_evaluated(&self) -> bool {
        self.evaluated
    }
}

impl Eval {
    pub fn new(ast: Ast) -> Self {
        Eval {
            ast: ast,
            stack: Vec::new(),
            evaluated: false
        }
    }

    pub fn new_option(ast: Option<Ast>) -> Self {
        match ast {
            Some(tree) => Eval {
                ast: tree,
                stack: Vec::new(),
                evaluated: false
            },
            None => panic!()
        }
    }

    fn expand_function(&mut self, scope: &Scope) {

    }

    fn eval_node(&mut self, mut scope: Scope) -> Scope {
        match self.stack.pop() {
            Some(mut current) => {
                match current.0.get_child(0) {
                    Some(mut child) => {
                        self.stack.push(current);
                        if child.node_val.is_some() {
                            let tok = child.node_val.unwrap();
                            if tok.tok_type == Type::Func {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                                self.expand_function(&scope);
                            } else {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                            }
                        } else {
                            self.stack.push((child, 0));
                        }
                    },
                    None => {
                        match self.stack.pop() {
                            Some(mut parent) => {
                                let new_index = current.1 + 1;
                                parent.0.insert_child(current.0, current.1);
                                match parent.0.child_count() > new_index {
                                    true => {
                                        let new_child = parent.0.get_child(new_index);
                                        self.stack.push(parent);
                                        self.stack.push((new_child.unwrap(), new_index));
                                    },
                                    false => {
                                        self.stack.push(parent);
                                        scope.evaluate_scope = true;
                                    }
                                }
                            },
                            None => self.evaluated = true
                        }
                    }
                }
            },
            None => {
                match self.ast.get_child(0) {
                    Some(mut child) => {
                        if child.node_val.is_some() {
                            let tok = child.node_val.unwrap();
                            if tok.tok_type == Type::Func {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                                self.expand_function(&scope);
                            } else {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                            }
                        } else {
                            self.stack.push((child, 0));
                        }
                    },
                    None => self.evaluated = true
                }
            }
        }
        if self.stack.is_empty() && self.ast.child_count() == 0 {
            self.evaluated = true;
        }
        scope
    }
}

struct Scope {
    pub parent: Option<Box<Scope>>,
    funcs: Vec<Ast>,
    in_builtin: bool,
    pub evaluate_scope: bool
}

impl Scope {
    pub fn new(parent: Scope) -> Self {
        Scope {
            parent: Some(Box::new(parent)),
            funcs: Vec::new(),
            in_builtin: false,
            evaluate_scope: false
        }
    }

    pub fn new_root() -> Self {
        Scope {
            parent: None,
            funcs: Vec::new(),
            in_builtin: false,
            evaluate_scope: false
        }
    }
}
<commit_msg>refactor that doesn't matter<commit_after>use ast::{Ast, AstTrait};
use token::{TokenTrait, Type};

pub struct Eval {
    ast: Ast,
    stack: Vec<(Ast, usize)>,
    evaluated: bool
}

pub trait EvalTrait {
    fn eval(&mut self);
    fn is_evaluated(&self) -> bool;
}

pub trait PrettyPrint {
    fn pretty_print(&mut self) -> String;
    fn push_whitespace(&self, pretty: &mut String);
}

impl PrettyPrint for Eval {
    fn push_whitespace(&self, pretty: &mut String) {
        for _ in 0..self.stack.len() {
            pretty.push('\t');
        }
    }

    fn pretty_print(&mut self) -> String {
        let mut pretty = String::new();
        loop {
            match self.stack.pop() {
                Some(mut current) => {
                    match current.0.get_child(0) {
                        Some(mut child) => {
                            self.stack.push(current);
                            if child.node_val.is_some() {
                                let tok = child.node_val.unwrap();
                                if tok.tok_type == Type::Oparen {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('(');
                                    pretty.push('\n');
                                } else if tok.tok_type == Type::OpenList {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('<');
                                    pretty.push('\n');
                                }
                                child.node_val = Some(tok);
                            }
                            self.stack.push((child, 0));
                        },
                        None => {
                            if current.0.node_val.is_some() {
                                let tok = current.0.node_val.unwrap();
                                self.push_whitespace(&mut pretty);
                                match tok.tok_type {
                                    Type::Oparen => pretty.push(')'),
                                    Type::OpenList => pretty.push('>'),
                                    _ => pretty.push_str(&tok.get_lexed())
                                }
                            }
                            pretty.push('\n');
                        }
                    }
                },
                None => {
                    match self.ast.get_child(0) {
                        Some(mut child) => {
                            if child.node_val.is_some() {
                                let tok = child.node_val.unwrap();
                                if tok.tok_type == Type::Oparen {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('(');
                                    pretty.push('\n');
                                } else if tok.tok_type == Type::OpenList {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('<');
                                    pretty.push('\n');
                                }
                                child.node_val = Some(tok);
                            }
                            self.stack.push((child, 0));
                        },
                        None => break
                    }
                }
            }
            if self.stack.is_empty() && self.ast.child_count() == 0 {
                break;
            }
        }
        pretty
    }
}

impl EvalTrait for Eval {
    fn eval(&mut self) {
        let mut scope = Scope::new_root();
        while !self.evaluated {
            scope = self.eval_node(scope); // If scope says evaluate, evaluate.
        }
    }

    fn is_evaluated(&self) -> bool {
        self.evaluated
    }
}

impl Eval {
    pub fn new(ast: Ast) -> Self {
        Eval {
            ast: ast,
            stack: Vec::new(),
            evaluated: false
        }
    }

    pub fn new_option(ast: Option<Ast>) -> Self {
        match ast {
            Some(tree) => Eval {
                ast: tree,
                stack: Vec::new(),
                evaluated: false
            },
            None => panic!()
        }
    }

    fn expand_function(&mut self, scope: &Scope) {

    }

    fn eval_node(&mut self, mut scope: Scope) -> Scope {
        match self.stack.pop() {
            Some(mut current) => {
                match current.0.get_child(0) {
                    Some(mut child) => {
                        self.stack.push(current);
                        if child.node_val.is_some() {
                            let tok = child.node_val.unwrap();
                            if tok.tok_type == Type::Func {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                                self.expand_function(&scope);
                            } else {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                            }
                        } else {
                            self.stack.push((child, 0));
                        }
                    },
                    None => {
                        match self.stack.pop() {
                            Some(mut parent) => {
                                let new_index = current.1 + 1;
                                parent.0.insert_child(current.0, current.1);
                                if parent.0.child_count() > new_index {
                                    let new_child = parent.0.get_child(new_index);
                                    self.stack.push(parent);
                                    self.stack.push((new_child.unwrap(), new_index));
                                } else {
                                    self.stack.push(parent);
                                    scope.evaluate_scope = true;
                                }
                            },
                            None => self.evaluated = true
                        }
                    }
                }
            },
            None => {
                match self.ast.get_child(0) {
                    Some(mut child) => {
                        if child.node_val.is_some() {
                            let tok = child.node_val.unwrap();
                            if tok.tok_type == Type::Func {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                                self.expand_function(&scope);
                            } else {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                            }
                        } else {
                            self.stack.push((child, 0));
                        }
                    },
                    None => self.evaluated = true
                }
            }
        }
        if self.stack.is_empty() && self.ast.child_count() == 0 {
            self.evaluated = true;
        }
        scope
    }
}

struct Scope {
    pub parent: Option<Box<Scope>>,
    funcs: Vec<Ast>,
    in_builtin: bool,
    pub evaluate_scope: bool
}

impl Scope {
    pub fn new(parent: Scope) -> Self {
        Scope {
            parent: Some(Box::new(parent)),
            funcs: Vec::new(),
            in_builtin: false,
            evaluate_scope: false
        }
    }

    pub fn new_root() -> Self {
        Scope {
            parent: None,
            funcs: Vec::new(),
            in_builtin: false,
            evaluate_scope: false
        }
    }
}
<|endoftext|>


<commit_before>use std::any::Any;
use std::io::Write;
use std::collections::{HashMap, VecDeque};

use template::Template;
use node::*;

type Variable<'a> = (String, &'a Box<Any>);

enum Dot { Dot }

static MAX_EXEC_DEPTH: usize = 100000;

struct State<'a, 'c, 'b, T: Write>
    where T: 'b
{
    template: &'a Template<'a>,
    writer: &'b mut T,
    node: Option<&'a Nodes>,
    vars: VecDeque<Variable<'a>>,
    depth: usize,
    dot: &'c Box<Any>,
}

impl<'a, 'b> Template<'a> {
    fn execute<T: Write>(&mut self, writer: &'b mut T, data: &'b Box<Any>) -> Result<(), String> {
        let mut vars = VecDeque::new();
        vars.push_back(("$".to_owned(), data));

        let mut state = State {
            template: &self,
            writer,
            node: None,
            vars,
            depth: 0,
            dot: data,
        };

        let root = self.tree_ids
            .get(&1usize)
            .and_then(|name| self.tree_set.get(name))
            .and_then(|tree| tree.root.as_ref())
            .ok_or_else(|| format!("{} is an incomplete or empty template", self.name))?;
        state.walk(data, root)?;

        Ok(())
    }
}

impl<'a, 'b, 'c, T: Write> State<'a, 'b, 'c, T> {
    fn walk_list(&mut self, dot: &Box<Any>, node: &'a ListNode) -> Result<(), String> {
        for n in &node.nodes {
            self.walk(dot, n)?;
        }
        Ok(())
    }

    fn walk(&mut self, dot: &Box<Any>, node: &'a Nodes) -> Result<(), String> {
        self.node = Some(node);
        match *node {
            Nodes::Action(_) => {
                let val = self.eval_pipeline(dot, node);
                return Ok(());
            }
            Nodes::If(_) => {
                return self.walk_if_or_with(node, dot);
            }
            Nodes::List(ref n) => return self.walk_list(dot, n),
            Nodes::Text(ref n) => write!(self.writer, "{}", n).map_err(|e| format!("{}", e))?,
            _ => {}
            // TODO
        }
        Ok(())
    }

    fn eval_pipeline(&mut self, dot: &Box<Any>, node: &'a Nodes) -> Result<Box<Any>, String> {
        self.node = Some(node);
        let mut val: Option<Box<Any>> = None;
        if let &Nodes::Pipe(ref pipe) = node {
            val = Some(self.eval_pipeline_raw(dot, pipe)?);
        }
        val.ok_or_else(|| format!("error evaluating pipeline {}", node))
    }

    fn eval_pipeline_raw(&mut self,
                         dot: &Box<Any>,
                         pipe: &'a PipeNode)
                         -> Result<Box<Any>, String> {
        let mut val: Option<Box<Any>> = None;
        for cmd in &pipe.cmds {
            val = Some(self.eval_command(dot, cmd, val)?);
            // TODO
        }
        val.ok_or_else(|| format!("error evaluating pipeline {}", pipe))
    }

    fn eval_command(&mut self,
                    dot: &Box<Any>,
                    cmd: &CommandNode,
                    val: Option<Box<Any>>)
                    -> Result<Box<Any>, String> {
        let first_word = &cmd.args
                              .first()
                              .ok_or_else(|| format!("no arguments for command node: {}", cmd))?;

        match *first_word {
            &Nodes::Field(ref n) => return self.eval_field_node(dot, n, &cmd.args, val),
            _ => {}
        }
        not_a_function(&cmd.args, val)?;
        match *first_word {
            &Nodes::Bool(ref n) => return Ok(Box::new(n.val)),
            &Nodes::Dot(_) => return Ok(Box::new(Dot::Dot)),
            _ => {}
        }

        Err(format!("DOOM"))
    }

    fn eval_field_node(&mut self,
                       dot: &Box<Any>,
                       field: &FieldNode,
                       args: &[Nodes],
                       val: Option<Box<Any>>)
                       -> Result<Box<Any>, String> {

        Err(format!("DOOM"))
    }

    fn walk_if_or_with(&mut self, node: &'a Nodes, dot: &Box<Any>) -> Result<(), String> {
        let pipe = match *node {
            Nodes::If(ref n) => &n.pipe,
            Nodes::With(ref n) => &n.pipe,
            _ => return Err(format!("expected if or with node, got {}", node)),
        };
        let val = self.eval_pipeline_raw(dot, &pipe)?;
        let truth = is_true(&val);
        if truth.0 {
            match *node {
                Nodes::If(ref n) => return self.walk_list(dot, &n.list),
                Nodes::With(ref n) => return self.walk_list(&val, &n.list),
                _ => {}
            }
        } else {
            match *node {
                Nodes::If(ref n) => {
                    if let Some(ref otherwise) = n.else_list {
                        return self.walk_list(dot, otherwise);
                    }
                }
                Nodes::With(ref n) => {
                    if let Some(ref otherwise) = n.else_list {
                        return self.walk_list(dot, otherwise);
                    }
                }
                _ => {}
            }
        }
        Ok(())
    }

    fn is_true(&self, val: &Box<Any>) -> (bool, bool) {
        if let Some(_) = val.downcast_ref::<Dot>() {
            println!("yay");
            return is_true(self.dot);
        }
        return is_true(val);
    }
}

fn not_a_function(args: &[Nodes], val: Option<Box<Any>>) -> Result<(), String> {
    if args.len() > 1 || val.is_some() {
        return Err(format!("can't give arument to non-function {}", args[0]));
    }
    Ok(())
}

macro_rules! non_zero {
    ($val:ident -> $($typ:ty),*) => {
        $(
            if let Some(i) = $val.downcast_ref::<$typ>() {
                return (i != &(0 as $typ), true);
            }
          )*
    }
}

fn is_true(val: &Box<Any>) -> (bool, bool) {
    if let Some(i) = val.downcast_ref::<bool>() {
        return (*i, true);
    }
    if let Some(s) = val.downcast_ref::<String>() {
        return (!s.is_empty(), true);
    }
    if let Some(v) = val.downcast_ref::<Vec<Box<Any>>>() {
        return (!v.is_empty(), true);
    }
    if let Some(v) = val.downcast_ref::<HashMap<String, Box<Any>>>() {
        return (!v.is_empty(), true);
    }

    non_zero!(val -> u8, u16, u32, u64, i8, i16, i32, i64, f32, f64);
    (true, true)
}

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

    #[test]
    fn test_is_true() {
        let t: Box<Any> = Box::new(1u32);
        assert_eq!(is_true(&t).0, true);
        let t: Box<Any> = Box::new(0u32);
        assert_eq!(is_true(&t).0, false);
    }

    #[test]
    fn simple_template() {
        let data: Box<Any> = Box::new(1);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if false }} 2000 {{ end }}"#).is_ok());
        let out = t.execute(&mut w, &data);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), "");

        let data: Box<Any> = Box::new(1);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if true }} 2000 {{ end }}"#).is_ok());
        let out = t.execute(&mut w, &data);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), " 2000 ");

        let data: Box<Any> = Box::new(1);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if true -}} 2000 {{- end }}"#).is_ok());
        let out = t.execute(&mut w, &data);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), "2000");

        let data: Box<Any> = Box::new(1);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if false -}} 2000 {{- else -}} 3000 {{- end }}"#)
                    .is_ok());
        let out = t.execute(&mut w, &data);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), "3000");
    }

    #[test]
    fn basic_dot() {
        let data: Box<Any> = Box::new(1);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if . -}} 2000 {{- else -}} 3000 {{- end }}"#)
                .is_ok());
        let out = t.execute(&mut w, &data);
        println!("{:?}", out);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), "2000");

        let data: Box<Any> = Box::new(false);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if . -}} 2000 {{- else -}} 3000 {{- end }}"#)
                .is_ok());
        let out = t.execute(&mut w, &data);
        println!("{:?}", out);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), "3000");
    }
}
<commit_msg>context (yay)<commit_after>use std::any::Any;
use std::io::Write;
use std::collections::{HashMap, VecDeque};

use template::Template;
use node::*;

type Variable<'a> = (String, &'a Box<Any>);

enum Dot {
    Dot,
}

static MAX_EXEC_DEPTH: usize = 100000;

struct State<'a, 'b, 'c, T: Write>
    where T: 'b
{
    template: &'a Template<'a>,
    writer: &'b mut T,
    node: Option<&'a Nodes>,
    vars: VecDeque<Variable<'a>>,
    depth: usize,
    dot: &'c Box<Any>,
}

struct Context<'d> {
    dot: &'d Box<Any>,
}

impl<'a, 'b> Template<'a> {
    fn execute<T: Write>(&mut self, writer: &'b mut T, data: &'b Box<Any>) -> Result<(), String> {
        let mut vars = VecDeque::new();
        vars.push_back(("$".to_owned(), data));

        let mut state = State {
            template: &self,
            writer,
            node: None,
            vars,
            depth: 0,
            dot: data,
        };

        let root = self.tree_ids
            .get(&1usize)
            .and_then(|name| self.tree_set.get(name))
            .and_then(|tree| tree.root.as_ref())
            .ok_or_else(|| format!("{} is an incomplete or empty template", self.name))?;
        let ctx = Context { dot: data };
        state.walk(&ctx, root)?;

        Ok(())
    }
}

impl<'a, 'b, 'c, T: Write> State<'a, 'b, 'c, T> {
    fn walk_list(&mut self, ctx: &Context, node: &'a ListNode) -> Result<(), String> {
        for n in &node.nodes {
            self.walk(ctx, n)?;
        }
        Ok(())
    }

    fn walk(&mut self, ctx: &Context, node: &'a Nodes) -> Result<(), String> {
        self.node = Some(node);
        match *node {
            Nodes::Action(_) => {
                let val = self.eval_pipeline(ctx, node);
                return Ok(());
            }
            Nodes::If(_) => {
                return self.walk_if_or_with(node, ctx);
            }
            Nodes::List(ref n) => return self.walk_list(ctx, n),
            Nodes::Text(ref n) => write!(self.writer, "{}", n).map_err(|e| format!("{}", e))?,
            _ => {}
            // TODO
        }
        Ok(())
    }

    fn eval_pipeline(&mut self, ctx: &Context, node: &'a Nodes) -> Result<Box<Any>, String> {
        self.node = Some(node);
        let mut val: Option<Box<Any>> = None;
        if let &Nodes::Pipe(ref pipe) = node {
            val = Some(self.eval_pipeline_raw(ctx, pipe)?);
        }
        val.ok_or_else(|| format!("error evaluating pipeline {}", node))
    }

    fn eval_pipeline_raw(&mut self, ctx: &Context, pipe: &'a PipeNode) -> Result<Box<Any>, String> {
        let mut val: Option<Box<Any>> = None;
        for cmd in &pipe.cmds {
            val = Some(self.eval_command(ctx, cmd, val)?);
            // TODO
        }
        val.ok_or_else(|| format!("error evaluating pipeline {}", pipe))
    }

    fn eval_command(&mut self,
                    ctx: &Context,
                    cmd: &CommandNode,
                    val: Option<Box<Any>>)
                    -> Result<Box<Any>, String> {
        let first_word = &cmd.args
                              .first()
                              .ok_or_else(|| format!("no arguments for command node: {}", cmd))?;

        match *first_word {
            &Nodes::Field(ref n) => return self.eval_field_node(ctx, n, &cmd.args, val),
            _ => {}
        }
        not_a_function(&cmd.args, val)?;
        match *first_word {
            &Nodes::Bool(ref n) => return Ok(Box::new(n.val)),
            &Nodes::Dot(_) => return Ok(Box::new(Dot::Dot)),
            _ => {}
        }

        Err(format!("DOOM"))
    }

    fn eval_field_node(&mut self,
                       ctx: &Context,
                       field: &FieldNode,
                       args: &[Nodes],
                       val: Option<Box<Any>>)
                       -> Result<Box<Any>, String> {

        Err(format!("DOOM"))
    }

    fn walk_if_or_with(&mut self, node: &'a Nodes, ctx: &Context) -> Result<(), String> {
        let pipe = match *node {
            Nodes::If(ref n) => &n.pipe,
            Nodes::With(ref n) => &n.pipe,
            _ => return Err(format!("expected if or with node, got {}", node)),
        };
        let val = self.eval_pipeline_raw(ctx, &pipe)?;
        let truth = self.is_true(ctx, &val);
        if truth.0 {
            match *node {
                Nodes::If(ref n) => self.walk_list(ctx, &n.list)?,
                Nodes::With(ref n) => {
                    let ctx = Context { dot: &val };
                    self.walk_list(&ctx, &n.list)?;
                }
                _ => {}
            }
        } else {
            match *node {
                Nodes::If(ref n) => {
                    if let Some(ref otherwise) = n.else_list {
                        self.walk_list(ctx, otherwise)?;
                    }
                }
                Nodes::With(ref n) => {
                    if let Some(ref otherwise) = n.else_list {
                        self.walk_list(ctx, otherwise)?;
                    }
                }
                _ => {}
            }
        }
        Ok(())
    }

    fn is_true(&self, ctx: &Context, val: &Box<Any>) -> (bool, bool) {
        if let Some(_) = val.downcast_ref::<Dot>() {
            return is_true(ctx.dot);
        }
        return is_true(val);
    }
}

fn not_a_function(args: &[Nodes], val: Option<Box<Any>>) -> Result<(), String> {
    if args.len() > 1 || val.is_some() {
        return Err(format!("can't give arument to non-function {}", args[0]));
    }
    Ok(())
}

macro_rules! non_zero {
    ($val:ident -> $($typ:ty),*) => {
        $(
            if let Some(i) = $val.downcast_ref::<$typ>() {
                return (i != &(0 as $typ), true);
            }
          )*
    }
}

fn is_true(val: &Box<Any>) -> (bool, bool) {
    if let Some(i) = val.downcast_ref::<bool>() {
        return (*i, true);
    }
    if let Some(s) = val.downcast_ref::<String>() {
        return (!s.is_empty(), true);
    }
    if let Some(v) = val.downcast_ref::<Vec<Box<Any>>>() {
        return (!v.is_empty(), true);
    }
    if let Some(v) = val.downcast_ref::<HashMap<String, Box<Any>>>() {
        return (!v.is_empty(), true);
    }

    non_zero!(val -> u8, u16, u32, u64, i8, i16, i32, i64, f32, f64);
    (true, true)
}

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

    #[test]
    fn test_is_true() {
        let t: Box<Any> = Box::new(1u32);
        assert_eq!(is_true(&t).0, true);
        let t: Box<Any> = Box::new(0u32);
        assert_eq!(is_true(&t).0, false);
    }

    #[test]
    fn simple_template() {
        let data: Box<Any> = Box::new(1);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if false }} 2000 {{ end }}"#).is_ok());
        let out = t.execute(&mut w, &data);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), "");

        let data: Box<Any> = Box::new(1);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if true }} 2000 {{ end }}"#).is_ok());
        let out = t.execute(&mut w, &data);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), " 2000 ");

        let data: Box<Any> = Box::new(1);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if true -}} 2000 {{- end }}"#).is_ok());
        let out = t.execute(&mut w, &data);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), "2000");

        let data: Box<Any> = Box::new(1);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if false -}} 2000 {{- else -}} 3000 {{- end }}"#)
                    .is_ok());
        let out = t.execute(&mut w, &data);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), "3000");
    }

    #[test]
    fn basic_dot() {
        let data: Box<Any> = Box::new(1);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if . -}} 2000 {{- else -}} 3000 {{- end }}"#)
                    .is_ok());
        let out = t.execute(&mut w, &data);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), "2000");

        let data: Box<Any> = Box::new(false);
        let mut w: Vec<u8> = vec![];
        let mut t = Template::new("foo");
        assert!(t.parse(r#"{{ if . -}} 2000 {{- else -}} 3000 {{- end }}"#)
                    .is_ok());
        let out = t.execute(&mut w, &data);
        assert!(out.is_ok());
        assert_eq!(String::from_utf8(w).unwrap(), "3000");
    }
}
<|endoftext|>


<commit_before>use super::atom::Atom;

#[derive(Debug, PartialEq)]
pub enum Expr {
    Atom(Atom),

    // ( ... )
    Tuple(Vec<Atom>),

    // [ ... ]
    Array(Vec<Atom>),

    // { key val ... }
    Map(Vec<(Atom, Atom)>),
}
<commit_msg>Implement Display for Expr<commit_after>use std::fmt;
use super::atom::Atom;

#[derive(Debug, PartialEq)]
pub enum Expr {
    Atom(Atom),

    // ( ... )
    Tuple(Vec<Expr>), /* [ ... ]
                       * Array(Vec<Atom>),
                       *
                       * { key val ... }
                       * Map(Vec<(Atom, Atom)>),
                       * */
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Expr::Atom(ref a) => write!(f, "{}", a),
            Expr::Tuple(ref t) => {
                try!(write!(f, "("));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, ")")
            }
        }
    }
}

#[test]
fn test_display() {
    assert_eq!("12345", &format!("{}", Expr::Atom(Atom::UInt(12345))));
    assert_eq!("(12345)",
               &format!("{}", Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345))])));
    assert_eq!("(12345 abc)",
               &format!("{}",
                        Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345)),
                                         Expr::Atom(Atom::Str("abc".to_string()))])));
    assert_eq!("(12345 (abc))",
               &format!("{}",
                        Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345)),
                                         Expr::Tuple(vec![
                                         Expr::Atom(Atom::Str("abc".to_string()))
                                         ])])));

}
<|endoftext|>


<commit_before>
use std;
use std::num::FromPrimitive;
use std::c_str::CString;
use ffi;
use {
    FtResult,
    GlyphSlot,
    Matrix,
    Vector,
};

#[repr(u32)]
pub enum KerningMode {
    KerningDefault = ffi::FT_KERNING_DEFAULT,
    KerningUnfitted = ffi::FT_KERNING_UNFITTED,
    KerningUnscaled = ffi::FT_KERNING_UNSCALED
}

bitflags!(flags LoadFlag: i32 {
    const DEFAULT                    = ffi::FT_LOAD_DEFAULT,
    const NO_SCALE                   = ffi::FT_LOAD_NO_SCALE,
    const NO_HINTING                 = ffi::FT_LOAD_NO_HINTING,
    const RENDER                     = ffi::FT_LOAD_RENDER,
    const NO_BITMAP                  = ffi::FT_LOAD_NO_BITMAP,
    const VERTICAL_LAYOUT            = ffi::FT_LOAD_VERTICAL_LAYOUT,
    const FORCE_AUTOHINT             = ffi::FT_LOAD_FORCE_AUTOHINT,
    const CROP_BITMAP                = ffi::FT_LOAD_CROP_BITMAP,
    const PEDANTIC                   = ffi::FT_LOAD_PEDANTIC,
    const IGNORE_GLOBAL_ADVANCE_WITH = ffi::FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH,
    const NO_RECURSE                 = ffi::FT_LOAD_NO_RECURSE,
    const IGNORE_TRANSFORM           = ffi::FT_LOAD_IGNORE_TRANSFORM,
    const MONOCHROME                 = ffi::FT_LOAD_MONOCHROME,
    const LINEAR_DESIGN              = ffi::FT_LOAD_LINEAR_DESIGN,
    const NO_AUTOHINT                = ffi::FT_LOAD_NO_AUTOHINT,
    const LOAD_TARGET_NORMAL         = ffi::FT_LOAD_TARGET_NORMAL,
    const LOAD_TARGET_LIGHT          = ffi::FT_LOAD_TARGET_LIGHT,
    const LOAD_TARGET_MONO           = ffi::FT_LOAD_TARGET_MONO,
    const LOAD_TARGET_LCD            = ffi::FT_LOAD_TARGET_LCD,
    const LOAD_TARGET_LCD_V          = ffi::FT_LOAD_TARGET_LCD_V,
    const COLOR                      = ffi::FT_LOAD_COLOR
})

pub struct Face {
    library_raw: ffi::FT_Library,
    raw: ffi::FT_Face,
    glyph: GlyphSlot,
}

impl Face {
    pub fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_Face) -> Face {
        unsafe {
            ffi::FT_Reference_Library(library_raw);
        }

        Face {
            library_raw: library_raw,
            raw: raw,
            glyph: unsafe { GlyphSlot::from_raw(library_raw, (*raw).glyph) },
        }
    }

    pub fn attach_file(&self, filepathname: &str) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Attach_File(self.raw, filepathname.as_slice().as_ptr() as *const i8);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn reference(&self) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Reference_Face(self.raw);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_char_size(&self, char_width: ffi::FT_F26Dot6, char_height: ffi::FT_F26Dot6, horz_resolution: ffi::FT_UInt, vert_resolution: ffi::FT_UInt) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Set_Char_Size(self.raw, char_width, char_height, horz_resolution, vert_resolution);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_pixel_sizes(&self, pixel_width: ffi::FT_UInt, pixel_height: ffi::FT_UInt) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Set_Pixel_Sizes(self.raw, pixel_width, pixel_height);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn load_glyph(&self, glyph_index: ffi::FT_UInt, load_flags: LoadFlag) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Load_Glyph(self.raw, glyph_index, load_flags.bits);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn load_char(&self, char_code: ffi::FT_ULong, load_flags: LoadFlag) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Load_Char(self.raw, char_code, load_flags.bits);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_transform(&self, matrix: &Matrix, delta: &Vector) {
        unsafe {
            ffi::FT_Set_Transform(self.raw, matrix, delta);
        }
    }

    pub fn get_char_index(&self, charcode: ffi::FT_ULong) -> ffi::FT_UInt {
        unsafe {
            ffi::FT_Get_Char_Index(self.raw, charcode)
        }
    }

    pub fn get_kerning(&self, left_char_index: ffi::FT_UInt, right_char_index: ffi::FT_UInt, kern_mode: KerningMode)
        -> FtResult<Vector> {

        let vec = Vector { x: 0, y: 0 };

        let err_code = unsafe {
            ffi::FT_Get_Kerning(self.raw, left_char_index, right_char_index,
                                kern_mode as u32, std::mem::transmute(&vec))
        };

        if err_code == ffi::FT_Err_Ok {
            Ok(vec)
        } else {
            Err(FromPrimitive::from_i32(err_code).unwrap())
        }
    }

    // According to FreeType doc, each time you load a new glyph image,
    // the previous one is erased from the glyph slot.
    #[inline(always)]
    pub fn glyph(&self) -> &GlyphSlot {
        &self.glyph
    }

    #[inline(always)]
    pub fn has_horizontal(&self) -> bool {
        ffi::FT_HAS_HORIZONTAL(self.raw)
    }

    #[inline(always)]
    pub fn has_vertical(&self) -> bool {
        ffi::FT_HAS_VERTICAL(self.raw)
    }

    #[inline(always)]
    pub fn has_kerning(&self) -> bool {
        ffi::FT_HAS_KERNING(self.raw)
    }

    #[inline(always)]
    pub fn is_scalable(&self) -> bool {
        ffi::FT_IS_SCALABLE(self.raw)
    }

    #[inline(always)]
    pub fn is_sfnt(&self) -> bool {
        ffi::FT_IS_SFNT(self.raw)
    }

    #[inline(always)]
    pub fn is_fixed_width(&self) -> bool {
        ffi::FT_IS_FIXED_WIDTH(self.raw)
    }

    #[inline(always)]
    pub fn has_fixed_sizes(&self) -> bool {
        ffi::FT_HAS_FIXED_SIZES(self.raw)
    }

    #[inline(always)]
    pub fn has_glyph_names(&self) -> bool {
        ffi::FT_HAS_GLYPH_NAMES(self.raw)
    }

    #[inline(always)]
    pub fn is_cid_keyed(&self) -> bool {
        ffi::FT_IS_CID_KEYED(self.raw)
    }

    #[inline(always)]
    pub fn is_tricky(&self) -> bool {
        ffi::FT_IS_TRICKY(self.raw)
    }

    #[inline(always)]
    pub fn has_color(&self) -> bool {
        ffi::FT_HAS_COLOR(self.raw)
    }

    #[inline(always)]
    pub fn raw(&self) -> &ffi::FT_FaceRec {
        unsafe {
            &*self.raw
        }
    }

    #[inline(always)]
    pub fn ascender(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).ascender
        }
    }

    #[inline(always)]
    pub fn descender(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).descender
        }
    }

    #[inline(always)]
    pub fn height(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).height
        }
    }

    #[inline(always)]
    pub fn max_advance_width(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).max_advance_width
        }
    }

    #[inline(always)]
    pub fn max_advance_height(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).max_advance_height
        }
    }

    #[inline(always)]
    pub fn underline_position(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).underline_position
        }
    }

    #[inline(always)]
    pub fn underline_thickness(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).underline_thickness
        }
    }

    pub fn family_name(&self) -> Option<String> {

        let family_name_ptr = unsafe { (*self.raw).family_name };

        if family_name_ptr.is_null() {
            None
        } else {
            let family_name = unsafe { CString::new(family_name_ptr, false) };
            Some(family_name.as_str().unwrap().into_string())
        }
    }

    pub fn style_name(&self) -> Option<String> {

        let style_name_ptr = unsafe { (*self.raw).style_name };

        if style_name_ptr.is_null() {
            None
        } else {
            let style_name = unsafe { CString::new(style_name_ptr, false) };
            Some(style_name.as_str().unwrap().into_string())
        }
    }
}

impl Drop for Face {
    fn drop(&mut self) {
        unsafe {
            let err = ffi::FT_Done_Face(self.raw);
            if err != 0 {
                std::io::println(format!("Failed to drop face. Error Code: {}", err).as_slice());
            }
            ffi::FT_Done_Library(self.library_raw);
        }
    }
}

<commit_msg>Fix inconsistent names<commit_after>
use std;
use std::num::FromPrimitive;
use std::c_str::CString;
use ffi;
use {
    FtResult,
    GlyphSlot,
    Matrix,
    Vector,
};

#[repr(u32)]
pub enum KerningMode {
    KerningDefault = ffi::FT_KERNING_DEFAULT,
    KerningUnfitted = ffi::FT_KERNING_UNFITTED,
    KerningUnscaled = ffi::FT_KERNING_UNSCALED
}

bitflags!(flags LoadFlag: i32 {
    const DEFAULT                    = ffi::FT_LOAD_DEFAULT,
    const NO_SCALE                   = ffi::FT_LOAD_NO_SCALE,
    const NO_HINTING                 = ffi::FT_LOAD_NO_HINTING,
    const RENDER                     = ffi::FT_LOAD_RENDER,
    const NO_BITMAP                  = ffi::FT_LOAD_NO_BITMAP,
    const VERTICAL_LAYOUT            = ffi::FT_LOAD_VERTICAL_LAYOUT,
    const FORCE_AUTOHINT             = ffi::FT_LOAD_FORCE_AUTOHINT,
    const CROP_BITMAP                = ffi::FT_LOAD_CROP_BITMAP,
    const PEDANTIC                   = ffi::FT_LOAD_PEDANTIC,
    const IGNORE_GLOBAL_ADVANCE_WITH = ffi::FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH,
    const NO_RECURSE                 = ffi::FT_LOAD_NO_RECURSE,
    const IGNORE_TRANSFORM           = ffi::FT_LOAD_IGNORE_TRANSFORM,
    const MONOCHROME                 = ffi::FT_LOAD_MONOCHROME,
    const LINEAR_DESIGN              = ffi::FT_LOAD_LINEAR_DESIGN,
    const NO_AUTOHINT                = ffi::FT_LOAD_NO_AUTOHINT,
    const TARGET_NORMAL              = ffi::FT_LOAD_TARGET_NORMAL,
    const TARGET_LIGHT               = ffi::FT_LOAD_TARGET_LIGHT,
    const TARGET_MONO                = ffi::FT_LOAD_TARGET_MONO,
    const TARGET_LCD                 = ffi::FT_LOAD_TARGET_LCD,
    const TARGET_LCD_V               = ffi::FT_LOAD_TARGET_LCD_V,
    const COLOR                      = ffi::FT_LOAD_COLOR
})

pub struct Face {
    library_raw: ffi::FT_Library,
    raw: ffi::FT_Face,
    glyph: GlyphSlot,
}

impl Face {
    pub fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_Face) -> Face {
        unsafe {
            ffi::FT_Reference_Library(library_raw);
        }

        Face {
            library_raw: library_raw,
            raw: raw,
            glyph: unsafe { GlyphSlot::from_raw(library_raw, (*raw).glyph) },
        }
    }

    pub fn attach_file(&self, filepathname: &str) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Attach_File(self.raw, filepathname.as_slice().as_ptr() as *const i8);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn reference(&self) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Reference_Face(self.raw);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_char_size(&self, char_width: ffi::FT_F26Dot6, char_height: ffi::FT_F26Dot6, horz_resolution: ffi::FT_UInt, vert_resolution: ffi::FT_UInt) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Set_Char_Size(self.raw, char_width, char_height, horz_resolution, vert_resolution);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_pixel_sizes(&self, pixel_width: ffi::FT_UInt, pixel_height: ffi::FT_UInt) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Set_Pixel_Sizes(self.raw, pixel_width, pixel_height);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn load_glyph(&self, glyph_index: ffi::FT_UInt, load_flags: LoadFlag) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Load_Glyph(self.raw, glyph_index, load_flags.bits);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn load_char(&self, char_code: ffi::FT_ULong, load_flags: LoadFlag) -> FtResult<()> {
        unsafe {
            let err = ffi::FT_Load_Char(self.raw, char_code, load_flags.bits);
            if err == ffi::FT_Err_Ok {
                Ok(())
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn set_transform(&self, matrix: &Matrix, delta: &Vector) {
        unsafe {
            ffi::FT_Set_Transform(self.raw, matrix, delta);
        }
    }

    pub fn get_char_index(&self, charcode: ffi::FT_ULong) -> ffi::FT_UInt {
        unsafe {
            ffi::FT_Get_Char_Index(self.raw, charcode)
        }
    }

    pub fn get_kerning(&self, left_char_index: ffi::FT_UInt, right_char_index: ffi::FT_UInt, kern_mode: KerningMode)
        -> FtResult<Vector> {

        let vec = Vector { x: 0, y: 0 };

        let err_code = unsafe {
            ffi::FT_Get_Kerning(self.raw, left_char_index, right_char_index,
                                kern_mode as u32, std::mem::transmute(&vec))
        };

        if err_code == ffi::FT_Err_Ok {
            Ok(vec)
        } else {
            Err(FromPrimitive::from_i32(err_code).unwrap())
        }
    }

    // According to FreeType doc, each time you load a new glyph image,
    // the previous one is erased from the glyph slot.
    #[inline(always)]
    pub fn glyph(&self) -> &GlyphSlot {
        &self.glyph
    }

    #[inline(always)]
    pub fn has_horizontal(&self) -> bool {
        ffi::FT_HAS_HORIZONTAL(self.raw)
    }

    #[inline(always)]
    pub fn has_vertical(&self) -> bool {
        ffi::FT_HAS_VERTICAL(self.raw)
    }

    #[inline(always)]
    pub fn has_kerning(&self) -> bool {
        ffi::FT_HAS_KERNING(self.raw)
    }

    #[inline(always)]
    pub fn is_scalable(&self) -> bool {
        ffi::FT_IS_SCALABLE(self.raw)
    }

    #[inline(always)]
    pub fn is_sfnt(&self) -> bool {
        ffi::FT_IS_SFNT(self.raw)
    }

    #[inline(always)]
    pub fn is_fixed_width(&self) -> bool {
        ffi::FT_IS_FIXED_WIDTH(self.raw)
    }

    #[inline(always)]
    pub fn has_fixed_sizes(&self) -> bool {
        ffi::FT_HAS_FIXED_SIZES(self.raw)
    }

    #[inline(always)]
    pub fn has_glyph_names(&self) -> bool {
        ffi::FT_HAS_GLYPH_NAMES(self.raw)
    }

    #[inline(always)]
    pub fn is_cid_keyed(&self) -> bool {
        ffi::FT_IS_CID_KEYED(self.raw)
    }

    #[inline(always)]
    pub fn is_tricky(&self) -> bool {
        ffi::FT_IS_TRICKY(self.raw)
    }

    #[inline(always)]
    pub fn has_color(&self) -> bool {
        ffi::FT_HAS_COLOR(self.raw)
    }

    #[inline(always)]
    pub fn raw(&self) -> &ffi::FT_FaceRec {
        unsafe {
            &*self.raw
        }
    }

    #[inline(always)]
    pub fn ascender(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).ascender
        }
    }

    #[inline(always)]
    pub fn descender(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).descender
        }
    }

    #[inline(always)]
    pub fn height(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).height
        }
    }

    #[inline(always)]
    pub fn max_advance_width(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).max_advance_width
        }
    }

    #[inline(always)]
    pub fn max_advance_height(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).max_advance_height
        }
    }

    #[inline(always)]
    pub fn underline_position(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).underline_position
        }
    }

    #[inline(always)]
    pub fn underline_thickness(&self) -> ffi::FT_Short {
        unsafe {
            (*self.raw).underline_thickness
        }
    }

    pub fn family_name(&self) -> Option<String> {

        let family_name_ptr = unsafe { (*self.raw).family_name };

        if family_name_ptr.is_null() {
            None
        } else {
            let family_name = unsafe { CString::new(family_name_ptr, false) };
            Some(family_name.as_str().unwrap().into_string())
        }
    }

    pub fn style_name(&self) -> Option<String> {

        let style_name_ptr = unsafe { (*self.raw).style_name };

        if style_name_ptr.is_null() {
            None
        } else {
            let style_name = unsafe { CString::new(style_name_ptr, false) };
            Some(style_name.as_str().unwrap().into_string())
        }
    }
}

impl Drop for Face {
    fn drop(&mut self) {
        unsafe {
            let err = ffi::FT_Done_Face(self.raw);
            if err != 0 {
                std::io::println(format!("Failed to drop face. Error Code: {}", err).as_slice());
            }
            ffi::FT_Done_Library(self.library_raw);
        }
    }
}

<|endoftext|>


<commit_before>use std::collections::HashMap;

use quote::{Tokens, ToTokens};
use syn::{Body, Field, Ident, Variant, VariantData, MacroInput, Ty};
use utils::number_idents;

/// Provides the hook to expand `#[derive(From)]` into an implementation of `From`
pub fn expand(input: &MacroInput, _: &str) -> Tokens {
    let input_type = &input.ident;
    match input.body {
        Body::Struct(VariantData::Tuple(ref fields)) => tuple_from(input, fields),
        Body::Struct(VariantData::Struct(ref fields)) => struct_from(input, fields),
        Body::Enum(ref variants) => enum_from(input_type, variants),
        _ => panic!("Only tuple structs and enums can derive From"),
    }
}

pub fn from_impl<T: ToTokens>(input: &MacroInput, fields: &Vec<Field>, body: T) -> Tokens {
    let generics = &input.generics;
    let input_type = &input.ident;
    let original_types: &Vec<_> = &fields.iter().map(|f| &f.ty).collect();
    quote!{
        impl#generics ::std::convert::From<(#(#original_types),*)> for #input_type#generics {
            fn from(original: (#(#original_types),*)) -> #input_type#generics {
                #body
            }
        }
    }
}

fn tuple_from(input: &MacroInput, fields: &Vec<Field>) -> Tokens {
    let input_type = &input.ident;
    let body = if fields.len() == 1 {
        quote!(#input_type(original))
    } else {
        let field_names = &number_idents(fields.len());
        quote!(#input_type(#(original.#field_names),*))

    };
    from_impl(input, fields, body)
}

fn struct_from(input: &MacroInput, fields: &Vec<Field>) -> Tokens {
    let input_type = &input.ident;
    let body = if fields.len() == 1 {
        let field_name = &fields[0].ident;
        quote!(#input_type{#field_name :original})
    } else {
        let argument_field_names = &number_idents(fields.len());
        let field_names: &Vec<_> = &fields.iter().map(|f| f.ident.as_ref().unwrap()).collect();
        quote!(#input_type{#(#field_names: original.#argument_field_names),*})
    };
    from_impl(input, fields, body)
}

fn enum_from(enum_ident: &Ident, variants: &Vec<Variant>) -> Tokens {
    let mut types = vec![];
    let mut idents = vec![];
    let mut type_counts = HashMap::new();

    for variant in variants {
        match variant.data {
            VariantData::Tuple(ref structs) => {
                if structs.len() == 1 {
                    let ty = &structs[0].ty;
                    idents.push(&variant.ident);
                    types.push(ty);
                    let counter = type_counts.entry(ty).or_insert(0);
                    *counter += 1;
                }
            }
            _ => {}
        }
    }

    let mut tokens = Tokens::new();

    for (ident, old_type) in idents.iter().zip(types) {
        if *type_counts.get(&old_type).unwrap() != 1 {
            // If more than one newtype is present don't add automatic From, since it is
            // ambiguous.
            continue;
        }

        tokens.append(&quote!(
            impl ::std::convert::From<#old_type> for #enum_ident {
                fn from(original: #old_type) -> #enum_ident {
                    #enum_ident::#ident(original)
                }
            }
        )
            .to_string())
    }
    tokens
}
<commit_msg>Generics: Intermediate change for generics for enum From<commit_after>use std::collections::HashMap;

use quote::{Tokens, ToTokens};
use syn::{Body, Field, Ident, Variant, VariantData, MacroInput, Ty};
use utils::number_idents;

/// Provides the hook to expand `#[derive(From)]` into an implementation of `From`
pub fn expand(input: &MacroInput, _: &str) -> Tokens {
    let input_type = &input.ident;
    match input.body {
        Body::Struct(VariantData::Tuple(ref fields)) => tuple_from(input, fields),
        Body::Struct(VariantData::Struct(ref fields)) => struct_from(input, fields),
        Body::Enum(ref variants) => enum_from(input, variants),
        _ => panic!("Only tuple structs and enums can derive From"),
    }
}

pub fn from_impl<T: ToTokens>(input: &MacroInput, fields: &Vec<Field>, body: T) -> Tokens {
    let generics = &input.generics;
    let input_type = &input.ident;
    let original_types: &Vec<_> = &fields.iter().map(|f| &f.ty).collect();
    quote!{
        impl#generics ::std::convert::From<(#(#original_types),*)> for #input_type#generics {
            fn from(original: (#(#original_types),*)) -> #input_type#generics {
                #body
            }
        }
    }
}

fn tuple_from(input: &MacroInput, fields: &Vec<Field>) -> Tokens {
    let input_type = &input.ident;
    let body = if fields.len() == 1 {
        quote!(#input_type(original))
    } else {
        let field_names = &number_idents(fields.len());
        quote!(#input_type(#(original.#field_names),*))

    };
    from_impl(input, fields, body)
}

fn struct_from(input: &MacroInput, fields: &Vec<Field>) -> Tokens {
    let input_type = &input.ident;
    let body = if fields.len() == 1 {
        let field_name = &fields[0].ident;
        quote!(#input_type{#field_name :original})
    } else {
        let argument_field_names = &number_idents(fields.len());
        let field_names: &Vec<_> = &fields.iter().map(|f| f.ident.as_ref().unwrap()).collect();
        quote!(#input_type{#(#field_names: original.#argument_field_names),*})
    };
    from_impl(input, fields, body)
}

fn enum_from(input: &MacroInput, variants: &Vec<Variant>) -> Tokens {
    let mut types = vec![];
    let mut idents = vec![];
    let mut type_counts = HashMap::new();

    for variant in variants {
        match variant.data {
            VariantData::Tuple(ref fields) => {
                let original_types: &Vec<_> = &fields.iter().map(|f| &f.ty).collect();
                idents.push(&variant.ident);
                types.push(original_types);
                let counter = type_counts.entry(original_types).or_insert(0);
                *counter += 1;
            }
            VariantData::Struct(ref fields) => {}
            _ => {}
        }
    }

    let mut tokens = Tokens::new();

    for (ident, old_type) in idents.iter().zip(types) {
        if *type_counts.get(&old_type).unwrap() != 1 {
            // If more than one variant is present with the same type signature don't
            // add automatic From, since it is ambiguous.
            continue;
        }

        tokens.append(&quote!{
            impl ::std::convert::From<#old_type> for #enum_ident {
                fn from(original: #old_type) -> #enum_ident {
                    #enum_ident::#ident(original)
                }
            }
        }
            .to_string())
    }
    tokens
}
<|endoftext|>


<commit_before>use std::fmt;
use std::rand;

#[deriving(Eq, Show)]
pub enum Direction {
    Up,
    Right,
    Down,
    Left,
}

impl Direction {
    fn to_vector(self) -> (int, int) {
        match self {
            Up    => (0, -1),
            Right => (1, 0),
            Down  => (0, 1),
            Left  => (-1, 0)
        }
    }

    // Haskell succ/pred???
    fn all_directions() -> ~[Direction] {
        ~[Up, Right, Down, Left]
    }

}

pub struct Traversal {
    xs: ~[uint],
    ys: ~[uint],

    idx: uint,
    max_idx: uint,
    size: uint
}

impl Traversal {
    pub fn new(size: uint, dir: Direction) -> Traversal {
        let (x, y) = dir.to_vector();
        let mut xs = range(0u, size).collect::<Vec<uint>>();
        let mut ys = range(0u, size).collect::<Vec<uint>>();
        if x == 1 {
            xs.reverse()
        }
        if y == 1 {
            ys.reverse()
        }
        Traversal { xs: xs.as_slice().into_owned(), ys: ys.as_slice().into_owned(),
                    idx: 0, max_idx: size * size,
                    size: size,
        }
    }
}

impl Iterator<(uint, uint)> for Traversal {
    fn next(&mut self) -> Option<(uint, uint)> {
        if self.idx == self.max_idx {
            None
        } else {
            let ret = (self.xs[self.idx / self.size],
                       self.ys[self.idx % self.size]);
            self.idx += 1;
            Some(ret)
        }
    }
}

#[deriving(Eq, Clone)]
pub struct Tile {
    pub x: uint,
    pub y: uint,
    pub value: int,

    pub prev_pos: Option<(uint, uint)>,
    pub merged_from: Option<((uint,uint), (uint, uint))>
}

impl Tile {
    pub fn new((x, y): (uint, uint), value: int) -> Tile {
        Tile { x: x, y: y, value: value,
               prev_pos: None, merged_from: None }
    }

    pub fn save_position(&mut self) {
        self.prev_pos = Some((self.x, self.y));
    }

    pub fn update_position(&mut self, (x, y): (uint, uint)) {
        self.x = x;
        self.y = y
    }

    pub fn pos(&self) -> (uint, uint) {
        (self.x, self.y)
    }

}

impl fmt::Show for Tile {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:4d}]", self.value)
    }
}

// Layout for console debug
//
// +-----+-----+-----+-----+
// |(0,0)|(0,1)|     |     |
// +-----+-----+-----+-----+
// |(1,0)|     |     |     |
// +-----+-----+-----+-----+
// |     |     |     |     |
// +-----+-----+-----+-----+
// |     |     |     |(3,3)|
// +-----+-----+-----+-----+
//
//

#[deriving(Eq, Show, Clone)]
pub struct Grid {
    pub size: uint,
    pub cells: Vec<Vec<Option<Tile>>>
}

impl Grid {
    pub fn new(size: uint) -> Grid {
        Grid {
            size: size,
            cells: Vec::from_elem(size,
                                  Vec::from_elem(size, None))
        }
    }

    pub fn random_available_cell(&self) -> Option<(uint, uint)> {
        let cells = self.available_cells();

        match cells.len() {
            0 => None,
            n => {
                Some(*cells.get(rand::random::<uint>() % n))
            }
        }
    }

    pub fn available_cells(&self) -> Vec<(uint, uint)> {
        let mut cells = Vec::new();

        self.each_cell(|x, y, tile| {
            if tile.is_none() {
                cells.push((x,y))
            }
        });
        cells
    }

    pub fn each_cell(&self, callback: |uint, uint, Option<&Tile>|) {
        for x in range(0u, self.size) {
            for y in range(0u, self.size) {
                callback(x, y, self.cells.get(x).get(y).as_ref())
            }
        }
    }

    pub fn each_mut_cell(&mut self, callback: |uint, uint, &mut Option<Tile>|) {
        for x in range(0u, self.size) {
            for y in range(0u, self.size) {
                callback(x, y, self.cells.get_mut(x).get_mut(y))
            }
        }
    }

    pub fn cells_available(&self) -> bool {
        self.available_cells().len() != 0
    }

    pub fn cell_available(&self, (x, y): (uint, uint)) -> bool {
        self.cells.get(x).get(y).is_none()
    }

    pub fn cell_occupied(&self, (x, y): (uint, uint)) -> bool {
        self.cells.get(x).get(y).is_some()
    }

    pub fn insert_tile(&mut self, tile: Tile) {
        *self.cells.get_mut(tile.x).get_mut(tile.y) = Some(tile);
    }

    pub fn remove_tile(&mut self, tile: Tile) {
        println!("remove ({}, {})", tile.x, tile.y);
        *self.cells.get_mut(tile.x).get_mut(tile.y) = None;
    }

    pub fn within_bounds(&self, (x, y): (uint, uint)) -> bool {
        x < self.size && y < self.size
    }

    pub fn cell_content(&self, (x, y): (uint, uint)) -> Option<Tile> {
        if self.within_bounds((x, y)) {
            *self.cells.get(x).get(y)
        } else {
            None
        }
    }

    pub fn debug_print(&self) {
        for col in self.cells.iter() {
            for cell in col.iter() {
                match *cell {
                    Some(t) => print!("{}\t", t),
                    None    => print!("[    ]\t"),
                }
            }
            println!("");
        }
    }

}

#[deriving(Show)]
pub struct GameManager {
    pub size: uint,
    pub start_tiles: uint,

    pub grid: Grid,
    pub score: uint,
    pub playing: bool
}

impl GameManager {
    pub fn new(size: uint) -> GameManager {
        GameManager { size: size,
                      start_tiles: 2,
                      grid: Grid::new(size),
                      score: 0,
                      playing: false }
    }

    pub fn setup(&mut self) {
        self.playing = true;

        self.add_start_tiles();
    }

    pub fn add_random_tile(&mut self) {
        if self.grid.cells_available() {
            let value = if rand::random::<uint>() % 10 < 9 { 2 } else { 4 };
            let tile = Tile::new(self.grid.random_available_cell().unwrap(), value);
            println!("add new at {}, val = {}", tile.pos(), value);
            self.grid.insert_tile(tile);
        }
    }

    fn add_start_tiles(&mut self) {
        for _ in range(0, self.start_tiles) {
            self.add_random_tile();
        }
    }

    pub fn prepare_tiles(&mut self) {
        self.grid.each_mut_cell(|_x, _y, tile| {
            if tile.is_some() {
                let mut t = tile.unwrap().clone();
                t.merged_from = None;
                t.save_position();
                *tile = Some(t);
            }
        })
    }

    pub fn move_tile(&mut self, tile: Tile, (x, y): (uint, uint)) {
        println!("move {} to {}", tile.pos(), (x,y));
        let mut tile = tile;
        *self.grid.cells.get_mut(tile.x).get_mut(tile.y) = None;
        tile.update_position((x, y));
        //*self.grid.cells.get_mut(tile.x).get_mut(tile.y) = None;
        let pos = self.grid.cells.get_mut(x).get_mut(y);
        *pos = Some(tile);
        //(*pos).unwrap().update_position((x, y));
    }

    pub fn move(&mut self, dir: Direction) -> bool {
        let mut moved = false;

        self.prepare_tiles();
        for (x, y) in self.build_traversal(dir) {
            let tile_opt = self.grid.cell_content((x, y));
            match tile_opt {
                Some(mut tile) => {
                    let (farthest_pos, next_pos) = self.find_farthest_position((x,y), dir.to_vector());
                    let next_opt = self.grid.cell_content(next_pos);
                    match next_opt {
                        Some(next) if next.value == tile.value && next.merged_from.is_none() => {
                            let mut merged = Tile::new(next_pos, tile.value * 2);
                            println!("{}, {} merged to {}", tile.pos(), next_pos, next_pos);
                            merged.merged_from = Some((tile.pos(), next.pos()));

                            self.grid.insert_tile(merged);
                            self.grid.remove_tile(tile);

                            tile.update_position(next_pos);

                            self.score += merged.value as uint;
                            // The mighty 2048 tile
                            moved = true;
                        }
                        _ => {
                            if tile.pos() != farthest_pos {
                                self.move_tile(tile, farthest_pos);
                                moved = true;
                            }
                        }
                    }
                }
                _ => ()
            }
        }

        if moved {
            // xxx moves_av
            println!("some cell moved, add new one!");
            self.add_random_tile();
        }

        moved
    }

    pub fn moves_available(&self) -> bool {
        self.grid.cells_available() || self.tile_matches_available()
    }

    // visit order
    fn build_traversal(&self, dir: Direction) -> Traversal {
        Traversal::new(self.size, dir)
    }

    fn find_farthest_position(&self, (x, y): (uint, uint), (dx, dy): (int, int)) -> ((uint, uint), (uint, uint)) {
        let (mut prev_x, mut prev_y) = (x as int, y as int);
        let (mut next_x, mut next_y) = (prev_x + dx, prev_y + dy);

        while self.grid.within_bounds((next_x as uint, next_y as uint)) &&
              self.grid.cell_available((next_x as uint, next_y as uint)) {
                  prev_x = next_x;
                  prev_y = next_y;
                  next_x = prev_x + dx;
                  next_y =  prev_y + dy;
        }
        // (farthest, next)
        ((prev_x as uint, prev_y as uint),
         (next_x as uint, next_y as uint))
    }

    fn tile_matches_available(&self) -> bool {
        for x in range(0u, self.size) {
            for y in range(0u, self.size) {
                match self.grid.cell_content((x,y)) {
                    Some(tile) => {
                        for dir in Direction::all_directions().iter() {
                            let (dx, dy) = dir.to_vector();
                            let nx = (x as int + dx) as uint;
                            let ny = (y as int + dy) as uint;
                            match self.grid.cell_content((nx, ny)) {
                                Some(other) if other.value == tile.value => {
                                    return true;
                                }
                                _ => ()
                            }
                        }

                    }
                    _ => ()
                }

            }
        }
        false
    }

}
<commit_msg>fix compile error: rename Eq to PartialEq<commit_after>use std::fmt;
use std::rand;

#[deriving(PartialEq, Show)]
pub enum Direction {
    Up,
    Right,
    Down,
    Left,
}

impl Direction {
    fn to_vector(self) -> (int, int) {
        match self {
            Up    => (0, -1),
            Right => (1, 0),
            Down  => (0, 1),
            Left  => (-1, 0)
        }
    }

    // Haskell succ/pred???
    fn all_directions() -> ~[Direction] {
        ~[Up, Right, Down, Left]
    }

}

pub struct Traversal {
    xs: ~[uint],
    ys: ~[uint],

    idx: uint,
    max_idx: uint,
    size: uint
}

impl Traversal {
    pub fn new(size: uint, dir: Direction) -> Traversal {
        let (x, y) = dir.to_vector();
        let mut xs = range(0u, size).collect::<Vec<uint>>();
        let mut ys = range(0u, size).collect::<Vec<uint>>();
        if x == 1 {
            xs.reverse()
        }
        if y == 1 {
            ys.reverse()
        }
        Traversal { xs: xs.as_slice().into_owned(), ys: ys.as_slice().into_owned(),
                    idx: 0, max_idx: size * size,
                    size: size,
        }
    }
}

impl Iterator<(uint, uint)> for Traversal {
    fn next(&mut self) -> Option<(uint, uint)> {
        if self.idx == self.max_idx {
            None
        } else {
            let ret = (self.xs[self.idx / self.size],
                       self.ys[self.idx % self.size]);
            self.idx += 1;
            Some(ret)
        }
    }
}

#[deriving(PartialEq, Clone)]
pub struct Tile {
    pub x: uint,
    pub y: uint,
    pub value: int,

    pub prev_pos: Option<(uint, uint)>,
    pub merged_from: Option<((uint,uint), (uint, uint))>
}

impl Tile {
    pub fn new((x, y): (uint, uint), value: int) -> Tile {
        Tile { x: x, y: y, value: value,
               prev_pos: None, merged_from: None }
    }

    pub fn save_position(&mut self) {
        self.prev_pos = Some((self.x, self.y));
    }

    pub fn update_position(&mut self, (x, y): (uint, uint)) {
        self.x = x;
        self.y = y
    }

    pub fn pos(&self) -> (uint, uint) {
        (self.x, self.y)
    }

}

impl fmt::Show for Tile {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:4d}]", self.value)
    }
}

// Layout for console debug
//
// +-----+-----+-----+-----+
// |(0,0)|(0,1)|     |     |
// +-----+-----+-----+-----+
// |(1,0)|     |     |     |
// +-----+-----+-----+-----+
// |     |     |     |     |
// +-----+-----+-----+-----+
// |     |     |     |(3,3)|
// +-----+-----+-----+-----+
//
//

#[deriving(PartialEq, Show, Clone)]
pub struct Grid {
    pub size: uint,
    pub cells: Vec<Vec<Option<Tile>>>
}

impl Grid {
    pub fn new(size: uint) -> Grid {
        Grid {
            size: size,
            cells: Vec::from_elem(size,
                                  Vec::from_elem(size, None))
        }
    }

    pub fn random_available_cell(&self) -> Option<(uint, uint)> {
        let cells = self.available_cells();

        match cells.len() {
            0 => None,
            n => {
                Some(*cells.get(rand::random::<uint>() % n))
            }
        }
    }

    pub fn available_cells(&self) -> Vec<(uint, uint)> {
        let mut cells = Vec::new();

        self.each_cell(|x, y, tile| {
            if tile.is_none() {
                cells.push((x,y))
            }
        });
        cells
    }

    pub fn each_cell(&self, callback: |uint, uint, Option<&Tile>|) {
        for x in range(0u, self.size) {
            for y in range(0u, self.size) {
                callback(x, y, self.cells.get(x).get(y).as_ref())
            }
        }
    }

    pub fn each_mut_cell(&mut self, callback: |uint, uint, &mut Option<Tile>|) {
        for x in range(0u, self.size) {
            for y in range(0u, self.size) {
                callback(x, y, self.cells.get_mut(x).get_mut(y))
            }
        }
    }

    pub fn cells_available(&self) -> bool {
        self.available_cells().len() != 0
    }

    pub fn cell_available(&self, (x, y): (uint, uint)) -> bool {
        self.cells.get(x).get(y).is_none()
    }

    pub fn cell_occupied(&self, (x, y): (uint, uint)) -> bool {
        self.cells.get(x).get(y).is_some()
    }

    pub fn insert_tile(&mut self, tile: Tile) {
        *self.cells.get_mut(tile.x).get_mut(tile.y) = Some(tile);
    }

    pub fn remove_tile(&mut self, tile: Tile) {
        println!("remove ({}, {})", tile.x, tile.y);
        *self.cells.get_mut(tile.x).get_mut(tile.y) = None;
    }

    pub fn within_bounds(&self, (x, y): (uint, uint)) -> bool {
        x < self.size && y < self.size
    }

    pub fn cell_content(&self, (x, y): (uint, uint)) -> Option<Tile> {
        if self.within_bounds((x, y)) {
            *self.cells.get(x).get(y)
        } else {
            None
        }
    }

    pub fn debug_print(&self) {
        for col in self.cells.iter() {
            for cell in col.iter() {
                match *cell {
                    Some(t) => print!("{}\t", t),
                    None    => print!("[    ]\t"),
                }
            }
            println!("");
        }
    }

}

#[deriving(Show)]
pub struct GameManager {
    pub size: uint,
    pub start_tiles: uint,

    pub grid: Grid,
    pub score: uint,
    pub playing: bool
}

impl GameManager {
    pub fn new(size: uint) -> GameManager {
        GameManager { size: size,
                      start_tiles: 2,
                      grid: Grid::new(size),
                      score: 0,
                      playing: false }
    }

    pub fn setup(&mut self) {
        self.playing = true;

        self.add_start_tiles();
    }

    pub fn add_random_tile(&mut self) {
        if self.grid.cells_available() {
            let value = if rand::random::<uint>() % 10 < 9 { 2 } else { 4 };
            let tile = Tile::new(self.grid.random_available_cell().unwrap(), value);
            println!("add new at {}, val = {}", tile.pos(), value);
            self.grid.insert_tile(tile);
        }
    }

    fn add_start_tiles(&mut self) {
        for _ in range(0, self.start_tiles) {
            self.add_random_tile();
        }
    }

    pub fn prepare_tiles(&mut self) {
        self.grid.each_mut_cell(|_x, _y, tile| {
            if tile.is_some() {
                let mut t = tile.unwrap().clone();
                t.merged_from = None;
                t.save_position();
                *tile = Some(t);
            }
        })
    }

    pub fn move_tile(&mut self, tile: Tile, (x, y): (uint, uint)) {
        println!("move {} to {}", tile.pos(), (x,y));
        let mut tile = tile;
        *self.grid.cells.get_mut(tile.x).get_mut(tile.y) = None;
        tile.update_position((x, y));
        //*self.grid.cells.get_mut(tile.x).get_mut(tile.y) = None;
        let pos = self.grid.cells.get_mut(x).get_mut(y);
        *pos = Some(tile);
        //(*pos).unwrap().update_position((x, y));
    }

    pub fn move(&mut self, dir: Direction) -> bool {
        let mut moved = false;

        self.prepare_tiles();
        for (x, y) in self.build_traversal(dir) {
            let tile_opt = self.grid.cell_content((x, y));
            match tile_opt {
                Some(mut tile) => {
                    let (farthest_pos, next_pos) = self.find_farthest_position((x,y), dir.to_vector());
                    let next_opt = self.grid.cell_content(next_pos);
                    match next_opt {
                        Some(next) if next.value == tile.value && next.merged_from.is_none() => {
                            let mut merged = Tile::new(next_pos, tile.value * 2);
                            println!("{}, {} merged to {}", tile.pos(), next_pos, next_pos);
                            merged.merged_from = Some((tile.pos(), next.pos()));

                            self.grid.insert_tile(merged);
                            self.grid.remove_tile(tile);

                            tile.update_position(next_pos);

                            self.score += merged.value as uint;
                            // The mighty 2048 tile
                            moved = true;
                        }
                        _ => {
                            if tile.pos() != farthest_pos {
                                self.move_tile(tile, farthest_pos);
                                moved = true;
                            }
                        }
                    }
                }
                _ => ()
            }
        }

        if moved {
            // xxx moves_av
            println!("some cell moved, add new one!");
            self.add_random_tile();
        }

        moved
    }

    pub fn moves_available(&self) -> bool {
        self.grid.cells_available() || self.tile_matches_available()
    }

    // visit order
    fn build_traversal(&self, dir: Direction) -> Traversal {
        Traversal::new(self.size, dir)
    }

    fn find_farthest_position(&self, (x, y): (uint, uint), (dx, dy): (int, int)) -> ((uint, uint), (uint, uint)) {
        let (mut prev_x, mut prev_y) = (x as int, y as int);
        let (mut next_x, mut next_y) = (prev_x + dx, prev_y + dy);

        while self.grid.within_bounds((next_x as uint, next_y as uint)) &&
              self.grid.cell_available((next_x as uint, next_y as uint)) {
                  prev_x = next_x;
                  prev_y = next_y;
                  next_x = prev_x + dx;
                  next_y =  prev_y + dy;
        }
        // (farthest, next)
        ((prev_x as uint, prev_y as uint),
         (next_x as uint, next_y as uint))
    }

    fn tile_matches_available(&self) -> bool {
        for x in range(0u, self.size) {
            for y in range(0u, self.size) {
                match self.grid.cell_content((x,y)) {
                    Some(tile) => {
                        for dir in Direction::all_directions().iter() {
                            let (dx, dy) = dir.to_vector();
                            let nx = (x as int + dx) as uint;
                            let ny = (y as int + dy) as uint;
                            match self.grid.cell_content((nx, ny)) {
                                Some(other) if other.value == tile.value => {
                                    return true;
                                }
                                _ => ()
                            }
                        }

                    }
                    _ => ()
                }

            }
        }
        false
    }

}
<|endoftext|>