<commit_before>mod terminal;
mod ansi;

use std::io::{self, Write, BufWriter};
use self::terminal::{Terminal, Event, Key};
use self::ansi::{clear, color, cursor, style};
use rayon::prelude::*;
use rff::choice::Choice;

#[derive(Debug)]
pub enum Error {
    Exit,
    Write(io::Error),
    Reset(terminal::Error)
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Write(err)
    }
}

impl From<terminal::Error> for Error {
    fn from(err: terminal::Error) -> Error {
        Error::Reset(err)
    }
}

pub struct Options {
    pub choices: Vec<String>,
    pub initial: String,
}

pub struct Interface {
    choices: Vec<String>,
    matches: Vec<Choice>,
    choices_width: usize,
    selected: usize,
    search: String,
    width: usize,
    terminal: Terminal,
}

impl Interface {
    /// Creates a new Interface from the provided options.
    pub fn from_opts(opts: Options) -> Interface {
        let mut term = Terminal::from("/dev/tty").unwrap();
        term.set_raw_mode().unwrap();

        let choices_width = format!("{}", opts.choices.len()).len();

        Interface {
            choices: opts.choices,
            matches: Vec::new(),
            choices_width: choices_width,
            selected: 0,
            search: opts.initial,
            width: term.max_width,
            terminal: term
        }
    }

    // Starts the interface
    pub fn run(&mut self) -> Result<&str, Error> {
        self.filter_choices();
        self.render()?;

        for event in self.terminal.events()? {
            if let Event::Key(key) = event? {
                match key {
                    Key::Ctrl('c') | Key::Ctrl('d') => {
                        self.clear()?;
                        return Err(Error::Exit);
                    }

                    Key::Char('\n') => {
                        break;
                    },

                    Key::Ctrl('n') => {
                        self.selected += 1;
                        self.clamp_selected();
                        self.render()?;
                    },

                    Key::Ctrl('p') => {
                        self.selected = self.selected.
                            checked_sub(1).
                            unwrap_or(0);

                        self.clamp_selected();
                        self.render()?;
                    },

                    Key::Char(ch) => {
                        self.search.push(ch);
                        self.filter_existing_matches();
                        self.render()?;
                    },

                    Key::Backspace | Key::Ctrl('h') => {
                        self.search.pop();
                        self.filter_choices();
                        self.render()?;
                    }

                    Key::Ctrl('u') => {
                        self.search.clear();
                        self.filter_choices();
                        self.render()?;
                    }

                    _ => {}
                }
            };
        }

        self.clear()?;
        Ok(self.result())
    }

    fn filter_choices(&mut self) {
        let mut matches = self.choices.
            par_iter().
            cloned().
            filter_map(|choice| Choice::with_positions(&self.search, choice)).
            collect::<Vec<_>>();

        matches.sort_by(|a, b| b.partial_cmp(a).unwrap());

        self.matches = matches;
    }

    fn filter_existing_matches(&mut self) {
        let mut matches = self.matches.
            par_iter().
            map(|c| c.text().to_string()).
            filter_map(|choice| Choice::with_positions(&self.search, choice)).
            collect::<Vec<_>>();

        matches.sort_by(|a, b| b.partial_cmp(a).unwrap());

        self.matches = matches;
    }

    fn prompt(&self) -> String {
        let count = self.matches.len();
        format!("{:width$} > {}", count, self.search, width = self.choices_width)
    }

    fn render(&mut self) -> io::Result<()> {
        let prompt = self.prompt();
        let matches = self.matches.iter().take(10);
        let n = matches.len() as u16;

        let mut term = BufWriter::new(&mut self.terminal);

        write!(term, "{}{}{}", cursor::Column(1), clear::Screen, prompt)?;

        for (i, choice) in matches.enumerate() {
            let selected = i == self.selected;
            let chars = choice.text().chars().take(self.width);

            write!(term, "\r\n")?;

            if selected {
                write!(term, "{}", style::Invert)?;
            }

            if let Some(positions) = choice.positions() {
                for (i, ch) in chars.enumerate() {
                    let is_match = positions.iter().any(|p| *p == i);

                    if is_match {
                        let color = color::Fg(color::Colors::Magenta);
                        let reset = color::Fg(color::Reset);
                        write!(term, "{}{}{}", color, ch, reset)?;
                    } else {
                        write!(term, "{}", ch)?;
                    }
                }
            } else {
                write!(term, "{}", chars.collect::<String>())?;
            }

            if selected {
                write!(term, "{}", style::NoInvert)?;
            }
        }

        if n > 0 {
            let col = (prompt.len() + 1) as u16;
            write!(term, "{}{}", cursor::Up(n), cursor::Column(col))?;
        }

        Ok(())
    }

    #[inline(always)]
    fn clamp_selected(&mut self) {
        let mut max = self.matches.len();
        if max > 10 { max = 10; }

        if self.selected >= max {
            self.selected = max - 1;
        }
    }

    fn clear(&mut self) -> Result<(), Error> {
        write!(self.terminal, "{}{}", cursor::Column(1), clear::Screen)?;
        self.terminal.reset()?;
        Ok(())
    }

    fn result(&mut self) -> &str {
        self.matches.iter().
            map(|c| c.text()).
            nth(self.selected).
            unwrap_or(&self.search)
    }
}
<commit_msg>Refinements to selected item position checking<commit_after>mod terminal;
mod ansi;

use std::io::{self, Write, BufWriter};
use self::terminal::{Terminal, Event, Key};
use self::ansi::{clear, color, cursor, style};
use rayon::prelude::*;
use rff::choice::Choice;

#[derive(Debug)]
pub enum Error {
    Exit,
    Write(io::Error),
    Reset(terminal::Error)
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Write(err)
    }
}

impl From<terminal::Error> for Error {
    fn from(err: terminal::Error) -> Error {
        Error::Reset(err)
    }
}

pub struct Options {
    pub choices: Vec<String>,
    pub initial: String,
}

pub struct Interface {
    choices: Vec<String>,
    matches: Vec<Choice>,
    choices_width: usize,
    selected: usize,
    search: String,
    width: usize,
    terminal: Terminal,
}

impl Interface {
    /// Creates a new Interface from the provided options.
    pub fn from_opts(opts: Options) -> Interface {
        let mut term = Terminal::from("/dev/tty").unwrap();
        term.set_raw_mode().unwrap();

        let choices_width = format!("{}", opts.choices.len()).len();

        Interface {
            choices: opts.choices,
            matches: Vec::new(),
            choices_width: choices_width,
            selected: 0,
            search: opts.initial,
            width: term.max_width,
            terminal: term
        }
    }

    // Starts the interface
    pub fn run(&mut self) -> Result<&str, Error> {
        self.filter_choices();
        self.render()?;

        for event in self.terminal.events()? {
            if let Event::Key(key) = event? {
                match key {
                    Key::Ctrl('c') | Key::Ctrl('d') => {
                        self.clear()?;
                        return Err(Error::Exit);
                    }

                    Key::Char('\n') => {
                        break;
                    },

                    Key::Ctrl('n') => {
                        self.selected += 1;
                        self.render()?;
                    },

                    Key::Ctrl('p') => {
                        self.selected = self.selected.saturating_sub(1);
                        self.render()?;
                    },

                    Key::Char(ch) => {
                        self.search.push(ch);
                        self.filter_existing_matches();
                        self.render()?;
                    },

                    Key::Backspace | Key::Ctrl('h') => {
                        self.search.pop();
                        self.filter_choices();
                        self.render()?;
                    }

                    Key::Ctrl('u') => {
                        self.search.clear();
                        self.filter_choices();
                        self.render()?;
                    }

                    _ => {}
                }
            };
        }

        self.clear()?;
        Ok(self.result())
    }

    fn filter_choices(&mut self) {
        let mut matches = self.choices.
            par_iter().
            cloned().
            filter_map(|choice| Choice::with_positions(&self.search, choice)).
            collect::<Vec<_>>();

        matches.sort_by(|a, b| b.partial_cmp(a).unwrap());

        self.matches = matches;
    }

    fn filter_existing_matches(&mut self) {
        let mut matches = self.matches.
            par_iter().
            map(|c| c.text().to_string()).
            filter_map(|choice| Choice::with_positions(&self.search, choice)).
            collect::<Vec<_>>();

        matches.sort_by(|a, b| b.partial_cmp(a).unwrap());

        self.matches = matches;
    }

    fn prompt(&self) -> String {
        let count = self.matches.len();
        format!("{:width$} > {}", count, self.search, width = self.choices_width)
    }

    fn render(&mut self) -> io::Result<()> {
        // ensure selected index is within bounds
        self.clamp_selected();

        let prompt = self.prompt();
        let matches = self.matches.iter().take(10);
        let n = matches.len() as u16;

        let mut term = BufWriter::new(&mut self.terminal);

        write!(term, "{}{}{}", cursor::Column(1), clear::Screen, prompt)?;

        for (i, choice) in matches.enumerate() {
            let selected = i == self.selected;
            let chars = choice.text().chars().take(self.width);

            write!(term, "\r\n")?;

            if selected {
                write!(term, "{}", style::Invert)?;
            }

            if let Some(positions) = choice.positions() {
                for (i, ch) in chars.enumerate() {
                    let is_match = positions.iter().any(|p| *p == i);

                    if is_match {
                        let color = color::Fg(color::Colors::Magenta);
                        let reset = color::Fg(color::Reset);
                        write!(term, "{}{}{}", color, ch, reset)?;
                    } else {
                        write!(term, "{}", ch)?;
                    }
                }
            } else {
                write!(term, "{}", chars.collect::<String>())?;
            }

            if selected {
                write!(term, "{}", style::NoInvert)?;
            }
        }

        if n > 0 {
            let col = (prompt.len() + 1) as u16;
            write!(term, "{}{}", cursor::Up(n), cursor::Column(col))?;
        }

        Ok(())
    }

    fn clamp_selected(&mut self) {
        let mut max = self.matches.len();
        if max > 10 { max = 10; }

        if self.selected >= max {
            self.selected = if max > 0 { max - 1 } else { 0 };
        }
    }

    fn clear(&mut self) -> Result<(), Error> {
        write!(self.terminal, "{}{}", cursor::Column(1), clear::Screen)?;
        self.terminal.reset()?;
        Ok(())
    }

    fn result(&mut self) -> &str {
        self.matches.iter().
            map(|c| c.text()).
            nth(self.selected).
            unwrap_or(&self.search)
    }
}
<|endoftext|>


<commit_before>use context::timeout;
use device::pic;
use device::serial::{COM1, COM2};
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

use time;
use context;

static PIT_TICKS: AtomicUsize = ATOMIC_USIZE_INIT;

unsafe fn trigger(irq: u8) {
    extern {
        fn irq_trigger(irq: u8);
    }

    if irq < 16 {
        if irq >= 8 {
            pic::SLAVE.mask_set(irq - 8);
            pic::MASTER.ack();
            pic::SLAVE.ack();
        } else {
            pic::MASTER.mask_set(irq);
            pic::MASTER.ack();
        }
    }

    irq_trigger(irq);
}

pub unsafe fn acknowledge(irq: usize) {
    if irq < 16 {
        if irq >= 8 {
            pic::SLAVE.mask_clear(irq as u8 - 8);
        } else {
            pic::MASTER.mask_clear(irq as u8);
        }
    }
}

interrupt!(pit, {
    // Saves CPU time by not sending IRQ event irq_trigger(0);

    const PIT_RATE: u64 = 2250286;

    {
        let mut offset = time::OFFSET.lock();
        let sum = offset.1 + PIT_RATE;
        offset.1 = sum % 1000000000;
        offset.0 += sum / 1000000000;
    }

    pic::MASTER.ack();

    if PIT_TICKS.fetch_add(1, Ordering::SeqCst) % 10 == 0 {
        context::switch();
    }

    // Any better way of doing this?
    timeout::trigger();
});

interrupt!(keyboard, {
    trigger(1);
});

interrupt!(cascade, {
    // No need to do any operations on cascade
    pic::MASTER.ack();
});

interrupt!(com2, {
    COM2.lock().receive();
    pic::MASTER.ack();
});

interrupt!(com1, {
    COM1.lock().receive();
    pic::MASTER.ack();
});

interrupt!(lpt2, {
    trigger(5);
});

interrupt!(floppy, {
    trigger(6);
});

interrupt!(lpt1, {
    trigger(7);
});

interrupt!(rtc, {
    trigger(8);
});

interrupt!(pci1, {
    trigger(9);
});

interrupt!(pci2, {
    trigger(10);
});

interrupt!(pci3, {
    trigger(11);
});

interrupt!(mouse, {
    trigger(12);
});

interrupt!(fpu, {
    trigger(13);
});

interrupt!(ata1, {
    trigger(14);
});

interrupt!(ata2, {
    trigger(15);
});
<commit_msg>Reset PIT_TICKS to 0 on context::switch, change condition for context::switch [irq]<commit_after>use context::timeout;
use device::pic;
use device::serial::{COM1, COM2};
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

use time;
use context;

static PIT_TICKS: AtomicUsize = ATOMIC_USIZE_INIT;

unsafe fn trigger(irq: u8) {
    extern {
        fn irq_trigger(irq: u8);
    }

    if irq < 16 {
        if irq >= 8 {
            pic::SLAVE.mask_set(irq - 8);
            pic::MASTER.ack();
            pic::SLAVE.ack();
        } else {
            pic::MASTER.mask_set(irq);
            pic::MASTER.ack();
        }
    }

    irq_trigger(irq);
}

pub unsafe fn acknowledge(irq: usize) {
    if irq < 16 {
        if irq >= 8 {
            pic::SLAVE.mask_clear(irq as u8 - 8);
        } else {
            pic::MASTER.mask_clear(irq as u8);
        }
    }
}

interrupt!(pit, {
    // Saves CPU time by not sending IRQ event irq_trigger(0);

    const PIT_RATE: u64 = 2250286;

    {
        let mut offset = time::OFFSET.lock();
        let sum = offset.1 + PIT_RATE;
        offset.1 = sum % 1000000000;
        offset.0 += sum / 1000000000;
    }

    pic::MASTER.ack();

    if PIT_TICKS.fetch_add(1, Ordering::SeqCst) >= 10 {
        PIT_TICKS.store(0, Ordering::SeqCst);
        assert_eq!(PIT_TICKS.load(Ordering::SeqCst), 0);
        context::switch();
    }

    // Any better way of doing this?
    timeout::trigger();
});

interrupt!(keyboard, {
    trigger(1);
});

interrupt!(cascade, {
    // No need to do any operations on cascade
    pic::MASTER.ack();
});

interrupt!(com2, {
    COM2.lock().receive();
    pic::MASTER.ack();
});

interrupt!(com1, {
    COM1.lock().receive();
    pic::MASTER.ack();
});

interrupt!(lpt2, {
    trigger(5);
});

interrupt!(floppy, {
    trigger(6);
});

interrupt!(lpt1, {
    trigger(7);
});

interrupt!(rtc, {
    trigger(8);
});

interrupt!(pci1, {
    trigger(9);
});

interrupt!(pci2, {
    trigger(10);
});

interrupt!(pci3, {
    trigger(11);
});

interrupt!(mouse, {
    trigger(12);
});

interrupt!(fpu, {
    trigger(13);
});

interrupt!(ata1, {
    trigger(14);
});

interrupt!(ata2, {
    trigger(15);
});
<|endoftext|>


<commit_before>
fn take_n<'r>(v: &'r [u8], n: uint) -> (&'r [u8], &'r [u8]) {
  (vec::slice(v, 0, n), vec::slice(v, n, v.len()))
}

fn take_atmost_n<'r>(v: &'r [u8], n: uint) -> (&'r [u8], &'r [u8]) {
  take_n(v, uint::min(n, v.len()))
}

fn take_head<'r>(v: &'r [u8]) -> (u8, &'r [u8]) {
  assert!(!v.is_empty());
  (*v.head(), vec::slice(v, 1, v.len()))
}

// in_integer
enum RedisType {
  TyNone,
  TyList,
  TyData,
  TyInt
}

enum Inside {
  in_start,
  in_number,
  in_number_digits_only,
  in_number_done,
  in_number_need_newline,
  in_data,
  //in_data_need_newline
}

struct RedisState {
  in: Inside,
  typ: RedisType,
  data_have: uint,
  number: uint, // also stores the data_size
  negative_number: bool,
}

enum RedisResult {
  Finished,
  NeedMore,
  Error
}

enum Result {
  Invalid,
  Nil,
  Int(int),
  Data(~[u8]),
  List(~[Result]),
  Err(~str),
  Status(~str)
}

// Return
trait Visitor {
  fn on_list(&mut self, len: uint) -> bool;

  fn on_data_beg(&mut self, len: uint);
  fn on_data(&mut self, data: &[u8]);
  fn on_data_end(&mut self) -> bool;

  fn on_integer(&mut self, num: uint, sign: bool) -> bool;

  fn on_nil(&mut self) -> bool;
}

// keep recursion in visitor?
struct MyVisitor {
  stack: ~[~[Result]], // (len, idx)
  result: Result
}

// returns true if we are finished parsing a redis request
fn element_done(visitor: &mut MyVisitor, value: Result) -> bool {
  if visitor.stack.is_empty() {
    visitor.result = value;
    true
  }
  else {

    vec::push(&mut (visitor.stack[0/*visitor.stack.len()-1*/]), value);
    false
/*      let (len, idx) = visitor.stack.last();
    assert!(idx+1 <= len);
    visitor.stack[visitor.stack.len()-1] = (len, idx+1);
    if idx + 1 == len {
      error!("Finsihed list");
      let _ = vec::pop(&mut visitor.stack);
      element_done(visitor)
    }
    else {
      false
    }
*/
  }
}

impl Visitor for MyVisitor {
  fn on_list(&mut self, len: uint) -> bool {
    error!("on_list(len: %u)", len);
    if len == 0 {
      element_done(self, List(~[]))
    }
    else {
      //vec::push(&mut self.stack, (len, 0));
      false
    }
  }

  fn on_data_beg(&mut self, len: uint) {
    error!("on_data_beg(len: %u)", len)
  }

  fn on_data(&mut self, data: &[u8]) {
    error!("on_data(%?)", data)
  }

  fn on_data_end(&mut self) -> bool {
    error!("on_data_end()");
    element_done(self, Data(~[1,2,3]))
  }

  fn on_integer(&mut self, num: uint, sign: bool) -> bool {
    error!("on_integer(%?, %?)", num, sign);
    element_done(self, Int(num as int)) // XXX
  }

  fn on_nil(&mut self) -> bool {
    error!("on_nil");
    element_done(self, Nil)
  }
}

fn parse_redis<'r, V: Visitor>(st: &mut RedisState, buf: &'r [u8], visitor: &mut V) -> (RedisResult, &'r [u8]) {
  let mut buf = buf;

  loop {

    match st.in {
      in_start => {
        if (buf.is_empty()) {break}

        let (c, b) = take_head(buf);
        buf = b;

        match c as char {
          '\r' | '\n' | ' ' =>  {
              error!("ignoring carriage return/new/whitespace line")
            }
          '*' => {
              st.typ = TyList;
              st.in = in_number;
              st.number = 0;
              st.negative_number = false;
            }
          '$' => {
              st.typ = TyData;
              st.in = in_number;
              st.number = 0;
              st.negative_number = false;
           }
          ':' => {
              st.typ = TyInt;
              st.in = in_number;
              st.number = 0;
              st.negative_number = false;
           }

           _ => {
              return (Error, buf) // XXX: return a slice including the character that failed
           }
        }

      }

      in_number => {
        if (buf.is_empty()) {break}
        let (c, b) = take_head(buf);
        buf = b;

        if c >= ('0' as u8) && c <= ('9' as u8) {
          st.number *= 10;
          st.number += (c - ('0' as u8)) as uint;
          st.in = in_number_digits_only;
        }
        else if c as char == '-' {
          st.negative_number = true;
          st.in = in_number_digits_only;
        }
        else if c as char == '\r' || c as char == ' ' {
          st.in = in_number_need_newline;
        }
        else if c as char == '\n' {
          st.in = in_number_done;
        }
        else {
          return (Error, buf)
        }
      }

      in_number_digits_only => {
        if (buf.is_empty()) {break}
        let (c, b) = take_head(buf);
        buf = b;

        if c >= ('0' as u8) && c <= ('9' as u8) {
          st.number *= 10;
          st.number += (c - ('0' as u8)) as uint;
        }
        else if c as char == '\r' || c as char == ' ' {
          st.in = in_number_need_newline;
        }
        else if c as char == '\n' {
          st.in = in_number_done;
        }
        else {
          return (Error, buf)
        }
      }

      in_number_need_newline => {
        if (buf.is_empty()) {break}
        let (c, b) = take_head(buf);
        buf = b;
        if c == ('\n' as u8) {
          st.in = in_number_done;
        }
        else {
          return (Error, buf)
        }
      }

      // XXX: make a function instead of a STATE
      in_number_done => {

        match st.typ {
          TyData | TyList => {
            if st.negative_number {
              if st.number == 1 {
                st.in = in_start;
                if visitor.on_nil() {
                  return (Finished, buf)
                }
              }
              else {
                return (Error, buf)
              }
            }
            else {
              match st.typ {
                TyData => {
                  st.data_have = 0;
                  st.in = in_data;
                  visitor.on_data_beg(st.number);
                }
                TyList => {
                  st.in = in_start;
                  if visitor.on_list(st.number) {
                    return (Finished, buf)
                  }
                }

                _ => { fail!() }
              }
            }
          }

          TyInt => {
            st.in = in_start;
            if visitor.on_integer(st.number, st.negative_number) {
              return (Finished, buf)
            }
          }

          _ => { fail!() }
        }
      }

      in_data => {
        if (buf.is_empty()) {break}
        let (data, b) = take_atmost_n(buf, st.number - st.data_have);
        buf = b;
        visitor.on_data(data);
        st.data_have += data.len();
        assert!(st.data_have <= st.number);
        if st.data_have == st.number {
          st.in = in_start;
          if visitor.on_data_end() {
            return (Finished, buf)
          }
        }
      }

    }
  }
  (NeedMore, buf)
}

fn main() {
  let mut st = RedisState {
    in: in_start,
    typ: TyNone,
    data_have: 0,
    number: 0,
    negative_number: false,
  };

  error!("%?", st);

  let mut visitor = MyVisitor {stack: ~[], result: Invalid};

  let s = ~"*4\r\n$3\r\nabc\r\n:123\n:1\n$-1\n";
  let slice = str::as_bytes_slice(s);
  let x = parse_redis(&mut st, slice, &mut visitor);
  error!("%?", st);
  error!("%?", x);
  error!("%?", visitor.result);
}
<commit_msg>Get rid of parser<commit_after><|endoftext|>


<commit_before>use lexer::*;
use ast::*;
use interner::InternedStr;

macro_rules! expect(
    ($e: expr, $p: ident (..)) => (
        match *$e.lexer.next() {
            x@$p(..) => x,
            x => {
                $e.lexer.backtrack();
                return Err(format!("Unexpected token {}, expected {}", x, stringify!($p)))
            }
        }
    );
    ($e: expr, $p: ident) => (
        match *$e.lexer.next() {
            x@$p => x,
            x => {
                $e.lexer.backtrack();
                return Err(format!("Unexpected token {}, expected {}", x, $p))
            }
        }
    )
)
macro_rules! expect1(
    ($e: expr, $p: ident ($x: ident)) => (
        match *$e.lexer.next() {
            $p($x) => $x,
            x => {
                $e.lexer.backtrack();
                return Err(format!("Unexpected token {}", x))
            }
        }
    )
)

macro_rules! matches(
    ($e: expr, $p: pat) => (
        match $e {
            $p => true,
            _ => false
        }
    )
)
fn precedence(s : &str) -> int {
    match s {
        "+" => 1,
        "-" => 1,
        "*" => 3,
        "/" => 3,
        "%" => 3,
        "==" => 1,
        "/=" => 1,
        "<" => 1,
        ">" => 1,
        "<=" => 1,
        ">=" => 1,
        _ => 9
    }
}

fn is_statement<T>(e: &Expr<T>) -> bool {
    match *e {
        IfElse(..) | Match(..) | Block(..) | While(..) => true,
        _ => false
    }
}

fn is_lvalue<T>(e: &Expr<T>) -> bool {
    match *e {
        Identifier(..) => true,
        _ => false
    }
}

type PString = InternedStr;
pub type ParseResult<T> = Result<T, String>;

pub struct Parser<'a, PString> {
    lexer: Lexer<'a>,
    make_id_f: |InternedStr|:'static -> PString
}

impl <'a, PString> Parser<'a, PString> {
    pub fn new(input: &'a mut Buffer, make_id: |InternedStr|:'static -> PString) -> Parser<'a, PString> {
        Parser { lexer: Lexer::new(input), make_id_f: make_id }
    }

    fn make_id(&mut self, s: InternedStr) -> PString {
        (self.make_id_f)(s)
    }

    pub fn module(&mut self) -> ParseResult<Module<PString>> {
        let mut fns = Vec::new();
        let mut structs = Vec::new();
        loop {
            match *self.lexer.peek() {
                TFn => fns.push(try!(self.function())),
                TStruct => structs.push(try!(self.struct_())),
                _ => break
            }
        }
        Ok(Module { functions: fns, structs: structs })
    }

    fn statement(&mut self) -> ParseResult<(Expr<PString>, bool)> {
        match *self.lexer.peek() {
            TLet => {
                self.lexer.next();
                let id = match expect!(self, TIdentifier(..)) {
                    TIdentifier(id) => id,
                    _ => fail!()
                };
                expect!(self, TAssign);
                let expr = try!(self.expression());
                expect!(self, TSemicolon);
                Ok((Let(self.make_id(id), box expr), true))
            }
            _ => {
                match self.expression() {
                    Ok(e) => {
                        if is_lvalue(&e) && matches!(self.lexer.peek(), &TAssign) {
                            self.lexer.next();
                            let rhs = try!(self.expression());
                            expect!(self, TSemicolon);
                            Ok((Assign(box e, box rhs), true))
                        }
                        else if is_statement(&e) {
                            Ok((e, true))
                        }
                        else if matches!(self.lexer.peek(), &TSemicolon) {
                            self.lexer.next();
                            Ok((e, true))
                        }
                        else {
                            Ok((e, false))
                        }
                    }
                    Err(e) => Err(e)
                }
            }
        }
    }

    pub fn expression(&mut self) -> ParseResult<Expr<PString>> {
        let e = try!(self.sub_expression());
        self.binary_expression(e, 0)
    }

    fn sub_expression(&mut self) -> ParseResult<Expr<PString>> {
        let e = try!(self.sub_expression_());
        match self.lexer.peek() {
            &TOpenParen => {
                let args = try!(self.parens(|this|
                    this.sep_by(|t| matches!(t, &TComma), |this| this.expression())
                ));
                Ok(Call(box e, args))
            }
            &TDot => {
                self.lexer.next();
                let id = expect1!(self, TIdentifier(x));
                Ok(FieldAccess(box e, self.make_id(id.clone())))
            }
            _ => Ok(e)
        }
    }

    fn sub_expression_(&mut self) -> ParseResult<Expr<PString>> {
        match *self.lexer.next() {
            TIdentifier(id) => {
                Ok(Identifier(self.make_id(id)))
            }
            TOpenParen => {
                let e = try!(self.expression());
                expect!(self, TCloseParen);
                Ok(e)
            }
            TOpenBrace => {
                self.lexer.backtrack();
                self.block()
            }
            TInteger(i) => {
                Ok(Literal(Integer(i)))
            }
            TFloat(f) => {
                Ok(Literal(Float(f)))
            }
            TString(s) => {
                Ok(Literal(String(s)))
            }
            TTrue => Ok(Literal(Bool(true))),
            TFalse => Ok(Literal(Bool(false))),
            TIf => {
                let pred = box try!(self.expression());
                let if_true = box try!(self.block());
                expect!(self, TElse);
                let if_false = box try!(self.block());
                Ok(IfElse(pred, if_true, if_false))
            }
            TWhile => {
                let pred = box try!(self.expression());
                let b = box try!(self.block());
                Ok(While(pred, b))
            }
            x => {
                self.lexer.backtrack();
                Err(format!("Token {} does not start an expression", x))
            }
        }
    }
    fn block(&mut self) -> ParseResult<Expr<PString>> {
        expect!(self, TOpenBrace);
        let mut exprs = Vec::new();
        while !matches!(self.lexer.peek(), &TCloseBrace) {
            let (expr, is_stm) = try!(self.statement());
            exprs.push(expr);
            if !is_stm {
                break
            }
        }
        expect!(self, TCloseBrace);
        Ok(Block(exprs))
    }

    fn binary_expression(&mut self, inL: Expr<PString>, minPrecedence : int) -> ParseResult<Expr<PString>> {
        let mut lhs = inL;
        self.lexer.next();
        loop {
            let lhs_op;
            let lhs_prec;
            match *self.lexer.current() {
                TOperator(op) => {
                    lhs_prec = precedence(op.as_slice());
                    lhs_op = op;
                    if lhs_prec < minPrecedence {
                        break
                    }
                }
                _ => break
            };
            debug!("Op {}", lhs_op);

            let mut rhs = try!(self.sub_expression());
            self.lexer.next();
            loop {
                let lookahead;
                match *self.lexer.current() {
                    TOperator(op) => {
                        lookahead = precedence(op.as_slice());
                        if lookahead < lhs_prec {
                            break
                        }
                        debug!("Inner op {}", op);
                    }
                    _ => break
                }
                self.lexer.backtrack();
                rhs = try!(self.binary_expression(rhs, lookahead));
                self.lexer.next();
            }
            lhs = BinOp(box lhs, self.make_id(lhs_op.clone()), box rhs)
        }
        self.lexer.backtrack();
        Ok(lhs)
    }

    fn typ(&mut self) -> ParseResult<Type<InternedStr>> {
        let x = expect1!(self, TIdentifier(x));
        Ok(Type(x))
    }

    fn field(&mut self) -> ParseResult<Field> {
        debug!("Field");
        let name = expect1!(self, TIdentifier(x));
        expect!(self, TColon);
        let typ = try!(self.typ());
        Ok(Field { name: name, typ: typ })
    }

    pub fn struct_(&mut self) -> ParseResult<Struct<PString>> {
        expect!(self, TStruct);
        let name = expect1!(self, TIdentifier(x));
        let fields = try!(self.braces(
            |this| this.sep_by(
                |t| *t == TComma, |this| this.field()
            )
        ));
        Ok(Struct { name: self.make_id(name), fields: fields })
    }

    pub fn function(&mut self) -> ParseResult<Function<PString>> {
        expect!(self, TFn);
        let name = expect1!(self, TIdentifier(x));
        let arguments = try!(self.parens(|this|
            this.sep_by(|t| matches!(t, &TComma), |this| this.field())
        ));
        let return_type = if matches!(self.lexer.peek(), &TRArrow) {
            self.lexer.next();
            try!(self.typ())
        }
        else {
            unit_type.clone()
        };
        let expr = try!(self.block());
        Ok(Function { name: self.make_id(name), arguments: arguments, return_type: return_type, expression: expr })
    }

    fn braces<T>(&mut self, f: |&mut Parser<'a, PString>| -> ParseResult<T>) -> ParseResult<T> {
        expect!(self, TOpenBrace);
        let x = try!(f(self));
        expect!(self, TCloseBrace);
        Ok(x)
    }

    fn parens<T>(&mut self, f: |&mut Parser<'a, PString>| -> ParseResult<T>) -> ParseResult<T> {
        expect!(self, TOpenParen);
        let x = try!(f(self));
        expect!(self, TCloseParen);
        Ok(x)
    }
    fn sep_by<T>(&mut self, sep: |&Token| -> bool, f: |&mut Parser<'a, PString>| -> ParseResult<T>) -> ParseResult<Vec<T>> {
        let mut result = Vec::new();
        match f(self) {
            Ok(x) => result.push(x),
            Err(_) => return Ok(result)
        }
        while sep(self.lexer.peek()) {
            self.lexer.next();
            let x = try!(f(self));
            result.push(x);
        }
        Ok(result)
    }
}

#[cfg(test)]
pub mod tests {
    use super::*;
    use super::ParseResult;
    use ast::*;
    use std::io::BufReader;
    use interner::*;

    type PExpr = Expr<InternedStr>;

    fn binop(l: PExpr, s: &str, r: PExpr) -> PExpr {
        BinOp(box l, intern(s), box r)
    }
    fn int(i: int) -> PExpr {
        Literal(Integer(i))
    }
    fn let_(s: &str, e: PExpr) -> PExpr {
        Let(intern(s), box e)
    }
    fn id(s: &str) -> PExpr {
        Identifier(intern(s))
    }
    fn field(s: &str, typ: Type<InternedStr>) -> Field {
        Field { name: intern(s), typ: typ }
    }
    fn typ(s: &str) -> Type<InternedStr> {
        Type(intern(s))
    }
    fn call(e: PExpr, args: Vec<PExpr>) -> PExpr {
        Call(box e, args)
    }
    fn if_else(p: PExpr, if_true: PExpr, if_false: PExpr) -> PExpr {
        IfElse(box p, box if_true, box if_false)
    }

    fn while_(p: PExpr, expr: PExpr) -> PExpr {
        While(box p, box expr)
    }
    fn assign(p: PExpr, rhs: PExpr) -> PExpr {
        Assign(box p, box rhs)
    }

    fn bool(b: bool) -> PExpr {
        Literal(Bool(b))
    }

    pub fn parse<T>(s: &str, f: |&mut Parser<InternedStr>|:'static -> ParseResult<T>) -> T {
        let mut buffer = BufReader::new(s.as_bytes());
        let mut parser = Parser::new(&mut buffer, |s| s);
        f(&mut parser)
            .unwrap_or_else(|err| fail!(err))
    }

    #[test]
    fn operators() {
        let expr = parse("1 / 4 + (2 - 3) * 2", |p| p.expression());
        assert_eq!(expr, binop(binop(int(1), "/", int(4)), "+", binop(binop(int(2), "-", int(3)), "*", int(2))));
    }
    #[test]
    fn block() {
        let expr = parse("1 / { let x = 2; x }", |p| p.expression());
        assert_eq!(expr, binop(int(1), "/", Block(vec!(let_("x", int(2)), id("x")))));
    }
    #[test]
    fn function() {
        let func = parse("fn main(x: int, y: float) { }", |p| p.function());
        let expected = Function {
            name: intern("main"),
            arguments: vec!(field("x", typ("int")), field("y", typ("float"))),
            expression: Block(vec!()),
            return_type: unit_type.clone()
        };
        assert_eq!(func, expected);
    }
    #[test]
    fn call_function() {
        let expr = parse("test(1, x)", |p| p.expression());
        assert_eq!(expr, call(id("test"), vec![int(1), id("x")]));
    }
    #[test]
    fn test_if_else() {
        let expr = parse("if 1 < x { 1 } else { 0 }", |p| p.expression());
        assert_eq!(expr, if_else(binop(int(1), "<", id("x")), Block(vec![int(1)]), Block(vec![int(0)])));
    }
    #[test]
    fn test_while() {
        let expr = parse("while true { }", |p| p.expression());
        assert_eq!(expr, while_(bool(true), Block(vec![])));
    }
    #[test]
    fn test_assign() {
        let expr = parse("{ y = 2; 2 }", |p| p.expression());
        assert_eq!(expr, Block(vec![assign(id("y"), int(2)), int(2)]));
    }
    #[test]
    fn struct_() {
        let module = parse("struct Test { y: int, f: float }", |p| p.module());
        let expected = Module {
            structs: vec![Struct {
                name: intern("Test"),
                fields: vec![field("y", typ("int")), field("f", typ("float"))]
            }],
            functions: vec![]
        };
        assert_eq!(module, expected);
    }
}
<commit_msg>Fix Type("int") ==> Literal(IntType) etc<commit_after>use lexer::*;
use ast::*;
use interner::InternedStr;

macro_rules! expect(
    ($e: expr, $p: ident (..)) => (
        match *$e.lexer.next() {
            x@$p(..) => x,
            x => {
                $e.lexer.backtrack();
                return Err(format!("Unexpected token {}, expected {}", x, stringify!($p)))
            }
        }
    );
    ($e: expr, $p: ident) => (
        match *$e.lexer.next() {
            x@$p => x,
            x => {
                $e.lexer.backtrack();
                return Err(format!("Unexpected token {}, expected {}", x, $p))
            }
        }
    )
)
macro_rules! expect1(
    ($e: expr, $p: ident ($x: ident)) => (
        match *$e.lexer.next() {
            $p($x) => $x,
            x => {
                $e.lexer.backtrack();
                return Err(format!("Unexpected token {}", x))
            }
        }
    )
)

macro_rules! matches(
    ($e: expr, $p: pat) => (
        match $e {
            $p => true,
            _ => false
        }
    )
)
fn precedence(s : &str) -> int {
    match s {
        "+" => 1,
        "-" => 1,
        "*" => 3,
        "/" => 3,
        "%" => 3,
        "==" => 1,
        "/=" => 1,
        "<" => 1,
        ">" => 1,
        "<=" => 1,
        ">=" => 1,
        _ => 9
    }
}

fn is_statement<T>(e: &Expr<T>) -> bool {
    match *e {
        IfElse(..) | Match(..) | Block(..) | While(..) => true,
        _ => false
    }
}

fn is_lvalue<T>(e: &Expr<T>) -> bool {
    match *e {
        Identifier(..) => true,
        _ => false
    }
}

type PString = InternedStr;
pub type ParseResult<T> = Result<T, String>;

pub struct Parser<'a, PString> {
    lexer: Lexer<'a>,
    make_id_f: |InternedStr|:'static -> PString
}

impl <'a, PString> Parser<'a, PString> {
    pub fn new(input: &'a mut Buffer, make_id: |InternedStr|:'static -> PString) -> Parser<'a, PString> {
        Parser { lexer: Lexer::new(input), make_id_f: make_id }
    }

    fn make_id(&mut self, s: InternedStr) -> PString {
        (self.make_id_f)(s)
    }

    pub fn module(&mut self) -> ParseResult<Module<PString>> {
        let mut fns = Vec::new();
        let mut structs = Vec::new();
        loop {
            match *self.lexer.peek() {
                TFn => fns.push(try!(self.function())),
                TStruct => structs.push(try!(self.struct_())),
                _ => break
            }
        }
        Ok(Module { functions: fns, structs: structs })
    }

    fn statement(&mut self) -> ParseResult<(Expr<PString>, bool)> {
        match *self.lexer.peek() {
            TLet => {
                self.lexer.next();
                let id = match expect!(self, TIdentifier(..)) {
                    TIdentifier(id) => id,
                    _ => fail!()
                };
                expect!(self, TAssign);
                let expr = try!(self.expression());
                expect!(self, TSemicolon);
                Ok((Let(self.make_id(id), box expr), true))
            }
            _ => {
                match self.expression() {
                    Ok(e) => {
                        if is_lvalue(&e) && matches!(self.lexer.peek(), &TAssign) {
                            self.lexer.next();
                            let rhs = try!(self.expression());
                            expect!(self, TSemicolon);
                            Ok((Assign(box e, box rhs), true))
                        }
                        else if is_statement(&e) {
                            Ok((e, true))
                        }
                        else if matches!(self.lexer.peek(), &TSemicolon) {
                            self.lexer.next();
                            Ok((e, true))
                        }
                        else {
                            Ok((e, false))
                        }
                    }
                    Err(e) => Err(e)
                }
            }
        }
    }

    pub fn expression(&mut self) -> ParseResult<Expr<PString>> {
        let e = try!(self.sub_expression());
        self.binary_expression(e, 0)
    }

    fn sub_expression(&mut self) -> ParseResult<Expr<PString>> {
        let e = try!(self.sub_expression_());
        match self.lexer.peek() {
            &TOpenParen => {
                let args = try!(self.parens(|this|
                    this.sep_by(|t| matches!(t, &TComma), |this| this.expression())
                ));
                Ok(Call(box e, args))
            }
            &TDot => {
                self.lexer.next();
                let id = expect1!(self, TIdentifier(x));
                Ok(FieldAccess(box e, self.make_id(id.clone())))
            }
            _ => Ok(e)
        }
    }

    fn sub_expression_(&mut self) -> ParseResult<Expr<PString>> {
        match *self.lexer.next() {
            TIdentifier(id) => {
                Ok(Identifier(self.make_id(id)))
            }
            TOpenParen => {
                let e = try!(self.expression());
                expect!(self, TCloseParen);
                Ok(e)
            }
            TOpenBrace => {
                self.lexer.backtrack();
                self.block()
            }
            TInteger(i) => {
                Ok(Literal(Integer(i)))
            }
            TFloat(f) => {
                Ok(Literal(Float(f)))
            }
            TString(s) => {
                Ok(Literal(String(s)))
            }
            TTrue => Ok(Literal(Bool(true))),
            TFalse => Ok(Literal(Bool(false))),
            TIf => {
                let pred = box try!(self.expression());
                let if_true = box try!(self.block());
                expect!(self, TElse);
                let if_false = box try!(self.block());
                Ok(IfElse(pred, if_true, if_false))
            }
            TWhile => {
                let pred = box try!(self.expression());
                let b = box try!(self.block());
                Ok(While(pred, b))
            }
            x => {
                self.lexer.backtrack();
                Err(format!("Token {} does not start an expression", x))
            }
        }
    }
    fn block(&mut self) -> ParseResult<Expr<PString>> {
        expect!(self, TOpenBrace);
        let mut exprs = Vec::new();
        while !matches!(self.lexer.peek(), &TCloseBrace) {
            let (expr, is_stm) = try!(self.statement());
            exprs.push(expr);
            if !is_stm {
                break
            }
        }
        expect!(self, TCloseBrace);
        Ok(Block(exprs))
    }

    fn binary_expression(&mut self, inL: Expr<PString>, minPrecedence : int) -> ParseResult<Expr<PString>> {
        let mut lhs = inL;
        self.lexer.next();
        loop {
            let lhs_op;
            let lhs_prec;
            match *self.lexer.current() {
                TOperator(op) => {
                    lhs_prec = precedence(op.as_slice());
                    lhs_op = op;
                    if lhs_prec < minPrecedence {
                        break
                    }
                }
                _ => break
            };
            debug!("Op {}", lhs_op);

            let mut rhs = try!(self.sub_expression());
            self.lexer.next();
            loop {
                let lookahead;
                match *self.lexer.current() {
                    TOperator(op) => {
                        lookahead = precedence(op.as_slice());
                        if lookahead < lhs_prec {
                            break
                        }
                        debug!("Inner op {}", op);
                    }
                    _ => break
                }
                self.lexer.backtrack();
                rhs = try!(self.binary_expression(rhs, lookahead));
                self.lexer.next();
            }
            lhs = BinOp(box lhs, self.make_id(lhs_op.clone()), box rhs)
        }
        self.lexer.backtrack();
        Ok(lhs)
    }

    fn typ(&mut self) -> ParseResult<Type<InternedStr>> {
        let x = expect1!(self, TIdentifier(x));
        Ok(match x.as_slice() {
            "int" => int_type.clone(),
            "float" => float_type.clone(),
            "string" => string_type.clone(),
            "bool" => bool_type.clone(),
            _ => Type(x)
        })
    }

    fn field(&mut self) -> ParseResult<Field> {
        debug!("Field");
        let name = expect1!(self, TIdentifier(x));
        expect!(self, TColon);
        let typ = try!(self.typ());
        Ok(Field { name: name, typ: typ })
    }

    pub fn struct_(&mut self) -> ParseResult<Struct<PString>> {
        expect!(self, TStruct);
        let name = expect1!(self, TIdentifier(x));
        let fields = try!(self.braces(
            |this| this.sep_by(
                |t| *t == TComma, |this| this.field()
            )
        ));
        Ok(Struct { name: self.make_id(name), fields: fields })
    }

    pub fn function(&mut self) -> ParseResult<Function<PString>> {
        expect!(self, TFn);
        let name = expect1!(self, TIdentifier(x));
        let arguments = try!(self.parens(|this|
            this.sep_by(|t| matches!(t, &TComma), |this| this.field())
        ));
        let return_type = if matches!(self.lexer.peek(), &TRArrow) {
            self.lexer.next();
            try!(self.typ())
        }
        else {
            unit_type.clone()
        };
        let expr = try!(self.block());
        Ok(Function { name: self.make_id(name), arguments: arguments, return_type: return_type, expression: expr })
    }

    fn braces<T>(&mut self, f: |&mut Parser<'a, PString>| -> ParseResult<T>) -> ParseResult<T> {
        expect!(self, TOpenBrace);
        let x = try!(f(self));
        expect!(self, TCloseBrace);
        Ok(x)
    }

    fn parens<T>(&mut self, f: |&mut Parser<'a, PString>| -> ParseResult<T>) -> ParseResult<T> {
        expect!(self, TOpenParen);
        let x = try!(f(self));
        expect!(self, TCloseParen);
        Ok(x)
    }
    fn sep_by<T>(&mut self, sep: |&Token| -> bool, f: |&mut Parser<'a, PString>| -> ParseResult<T>) -> ParseResult<Vec<T>> {
        let mut result = Vec::new();
        match f(self) {
            Ok(x) => result.push(x),
            Err(_) => return Ok(result)
        }
        while sep(self.lexer.peek()) {
            self.lexer.next();
            let x = try!(f(self));
            result.push(x);
        }
        Ok(result)
    }
}

#[cfg(test)]
pub mod tests {
    use super::*;
    use super::ParseResult;
    use ast::*;
    use std::io::BufReader;
    use interner::*;

    type PExpr = Expr<InternedStr>;

    fn binop(l: PExpr, s: &str, r: PExpr) -> PExpr {
        BinOp(box l, intern(s), box r)
    }
    fn int(i: int) -> PExpr {
        Literal(Integer(i))
    }
    fn let_(s: &str, e: PExpr) -> PExpr {
        Let(intern(s), box e)
    }
    fn id(s: &str) -> PExpr {
        Identifier(intern(s))
    }
    fn field(s: &str, typ: Type<InternedStr>) -> Field {
        Field { name: intern(s), typ: typ }
    }
    fn typ(s: &str) -> Type<InternedStr> {
        Type(intern(s))
    }
    fn call(e: PExpr, args: Vec<PExpr>) -> PExpr {
        Call(box e, args)
    }
    fn if_else(p: PExpr, if_true: PExpr, if_false: PExpr) -> PExpr {
        IfElse(box p, box if_true, box if_false)
    }

    fn while_(p: PExpr, expr: PExpr) -> PExpr {
        While(box p, box expr)
    }
    fn assign(p: PExpr, rhs: PExpr) -> PExpr {
        Assign(box p, box rhs)
    }

    fn bool(b: bool) -> PExpr {
        Literal(Bool(b))
    }

    pub fn parse<T>(s: &str, f: |&mut Parser<InternedStr>|:'static -> ParseResult<T>) -> T {
        let mut buffer = BufReader::new(s.as_bytes());
        let mut parser = Parser::new(&mut buffer, |s| s);
        f(&mut parser)
            .unwrap_or_else(|err| fail!(err))
    }

    #[test]
    fn operators() {
        let expr = parse("1 / 4 + (2 - 3) * 2", |p| p.expression());
        assert_eq!(expr, binop(binop(int(1), "/", int(4)), "+", binop(binop(int(2), "-", int(3)), "*", int(2))));
    }
    #[test]
    fn block() {
        let expr = parse("1 / { let x = 2; x }", |p| p.expression());
        assert_eq!(expr, binop(int(1), "/", Block(vec!(let_("x", int(2)), id("x")))));
    }
    #[test]
    fn function() {
        let func = parse("fn main(x: int, y: float) { }", |p| p.function());
        let expected = Function {
            name: intern("main"),
            arguments: vec!(field("x", typ("int")), field("y", typ("float"))),
            expression: Block(vec!()),
            return_type: unit_type.clone()
        };
        assert_eq!(func, expected);
    }
    #[test]
    fn call_function() {
        let expr = parse("test(1, x)", |p| p.expression());
        assert_eq!(expr, call(id("test"), vec![int(1), id("x")]));
    }
    #[test]
    fn test_if_else() {
        let expr = parse("if 1 < x { 1 } else { 0 }", |p| p.expression());
        assert_eq!(expr, if_else(binop(int(1), "<", id("x")), Block(vec![int(1)]), Block(vec![int(0)])));
    }
    #[test]
    fn test_while() {
        let expr = parse("while true { }", |p| p.expression());
        assert_eq!(expr, while_(bool(true), Block(vec![])));
    }
    #[test]
    fn test_assign() {
        let expr = parse("{ y = 2; 2 }", |p| p.expression());
        assert_eq!(expr, Block(vec![assign(id("y"), int(2)), int(2)]));
    }
    #[test]
    fn struct_() {
        let module = parse("struct Test { y: int, f: float }", |p| p.module());
        let expected = Module {
            structs: vec![Struct {
                name: intern("Test"),
                fields: vec![field("y", typ("int")), field("f", typ("float"))]
            }],
            functions: vec![]
        };
        assert_eq!(module, expected);
    }
}
<|endoftext|>


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

use helpers::HelperDef;
use registry::Registry;
use context::{Context, JsonTruthy, to_json};
use render::{Renderable, RenderContext, RenderError, Helper};

#[derive(Clone, Copy)]
pub struct WithHelper;

impl HelperDef for WithHelper {
    fn call(&self,
            c: &Context,
            h: &Helper,
            r: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let param = try!(h.param(0)
                          .ok_or_else(|| RenderError::new("Param not found for helper \"with\"")));

        let path = rc.get_path().clone();
        rc.promote_local_vars();
        if let Some(path_root) = param.path_root() {
            let local_path_root = format!("{}/{}", rc.get_path(), path_root);
            rc.set_local_path_root(local_path_root);
        }

        let not_empty = param.value().is_truthy();
        let template = if not_empty {
            h.template()
        } else {
            h.inverse()
        };

        if not_empty {
            if let Some(inner_path) = param.path() {
                let new_path = format!("{}/{}", path, inner_path);
                rc.set_path(new_path);
            }

            if let Some(block_param) = h.block_param() {
                let mut map = BTreeMap::new();
                map.insert(block_param.to_string(), to_json(param.value()));
                rc.push_block_context(&map);
            }
        }

        let rendered = match template {
            Some(t) => t.render(c, r, rc),
            None => Ok(()),
        };

        rc.set_path(path);
        rc.demote_local_vars();
        if not_empty {
            rc.pop_block_context();
        }
        rendered
    }
}

pub static WITH_HELPER: WithHelper = WithHelper;

#[cfg(test)]
#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))]
mod test {
    use template::Template;
    use registry::Registry;

    use std::collections::BTreeMap;
    use serialize::json::{Json, ToJson};

    struct Address {
        city: String,
        country: String,
    }

    impl ToJson for Address {
        fn to_json(&self) -> Json {
            let mut m = BTreeMap::new();
            m.insert("city".to_string(), self.city.to_json());
            m.insert("country".to_string(), self.country.to_json());
            Json::Object(m)
        }
    }

    struct Person {
        name: String,
        age: i16,
        addr: Address,
        titles: Vec<String>,
    }

    impl ToJson for Person {
        fn to_json(&self) -> Json {
            let mut m = BTreeMap::new();
            m.insert("name".to_string(), self.name.to_json());
            m.insert("age".to_string(), self.age.to_json());
            m.insert("addr".to_string(), self.addr.to_json());
            m.insert("titles".to_string(), self.titles.to_json());
            Json::Object(m)
        }
    }

    #[test]
    fn test_with() {
        let addr = Address {
            city: "Beijing".to_string(),
            country: "China".to_string(),
        };

        let person = Person {
            name: "Ning Sun".to_string(),
            age: 27,
            addr: addr,
            titles: vec!["programmer".to_string(), "cartographier".to_string()],
        };

        let t0 = Template::compile("{{#with addr}}{{city}}{{/with}}".to_string()).ok().unwrap();
        let t1 = Template::compile("{{#with notfound}}hello{{else}}world{{/with}}".to_string())
                     .ok()
                     .unwrap();
        let t2 = Template::compile("{{#with addr/country}}{{this}}{{/with}}".to_string())
                     .ok()
                     .unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);
        handlebars.register_template("t2", t2);

        let r0 = handlebars.render("t0", &person);
        assert_eq!(r0.ok().unwrap(), "Beijing".to_string());

        let r1 = handlebars.render("t1", &person);
        assert_eq!(r1.ok().unwrap(), "world".to_string());

        let r2 = handlebars.render("t2", &person);
        assert_eq!(r2.ok().unwrap(), "China".to_string());
    }

    #[test]
    fn test_with_in_each() {
        let addr = Address {
            city: "Beijing".to_string(),
            country: "China".to_string(),
        };

        let person = Person {
            name: "Ning Sun".to_string(),
            age: 27,
            addr: addr,
            titles: vec!["programmer".to_string(), "cartographier".to_string()],
        };

        let addr2 = Address {
            city: "Beijing".to_string(),
            country: "China".to_string(),
        };

        let person2 = Person {
            name: "Ning Sun".to_string(),
            age: 27,
            addr: addr2,
            titles: vec!["programmer".to_string(), "cartographier".to_string()],
        };

        let people = vec![person, person2];

        let t0 = Template::compile("{{#each this}}{{#with addr}}{{city}}{{/with}}{{/each}}"
                                       .to_string())
                     .ok()
                     .unwrap();
        let t1 = Template::compile("{{#each this}}{{#with addr}}{{../age}}{{/with}}{{/each}}"
                                       .to_string())
                     .ok()
                     .unwrap();
        let t2 = Template::compile("{{#each this}}{{#with addr}}{{@../index}}{{/with}}{{/each}}"
                                       .to_string())
                     .ok()
                     .unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);
        handlebars.register_template("t2", t2);

        let r0 = handlebars.render("t0", &people);
        assert_eq!(r0.ok().unwrap(), "BeijingBeijing".to_string());

        let r1 = handlebars.render("t1", &people);
        assert_eq!(r1.ok().unwrap(), "2727".to_string());

        let r2 = handlebars.render("t2", &people);
        assert_eq!(r2.ok().unwrap(), "01".to_string());
    }
}
<commit_msg>(test) with block param<commit_after>use std::collections::BTreeMap;

use helpers::HelperDef;
use registry::Registry;
use context::{Context, JsonTruthy, to_json};
use render::{Renderable, RenderContext, RenderError, Helper};

#[derive(Clone, Copy)]
pub struct WithHelper;

impl HelperDef for WithHelper {
    fn call(&self,
            c: &Context,
            h: &Helper,
            r: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let param = try!(h.param(0)
                          .ok_or_else(|| RenderError::new("Param not found for helper \"with\"")));

        let path = rc.get_path().clone();
        rc.promote_local_vars();
        if let Some(path_root) = param.path_root() {
            let local_path_root = format!("{}/{}", rc.get_path(), path_root);
            rc.set_local_path_root(local_path_root);
        }

        let not_empty = param.value().is_truthy();
        let template = if not_empty {
            h.template()
        } else {
            h.inverse()
        };

        if not_empty {
            if let Some(inner_path) = param.path() {
                let new_path = format!("{}/{}", path, inner_path);
                rc.set_path(new_path);
            }

            if let Some(block_param) = h.block_param() {
                let mut map = BTreeMap::new();
                map.insert(block_param.to_string(), to_json(param.value()));
                rc.push_block_context(&map);
            }
        }

        let rendered = match template {
            Some(t) => t.render(c, r, rc),
            None => Ok(()),
        };

        rc.set_path(path);
        rc.demote_local_vars();
        if not_empty {
            rc.pop_block_context();
        }
        rendered
    }
}

pub static WITH_HELPER: WithHelper = WithHelper;

#[cfg(test)]
#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))]
mod test {
    use template::Template;
    use registry::Registry;

    use std::collections::BTreeMap;
    use serialize::json::{Json, ToJson};

    struct Address {
        city: String,
        country: String,
    }

    impl ToJson for Address {
        fn to_json(&self) -> Json {
            let mut m = BTreeMap::new();
            m.insert("city".to_string(), self.city.to_json());
            m.insert("country".to_string(), self.country.to_json());
            Json::Object(m)
        }
    }

    struct Person {
        name: String,
        age: i16,
        addr: Address,
        titles: Vec<String>,
    }

    impl ToJson for Person {
        fn to_json(&self) -> Json {
            let mut m = BTreeMap::new();
            m.insert("name".to_string(), self.name.to_json());
            m.insert("age".to_string(), self.age.to_json());
            m.insert("addr".to_string(), self.addr.to_json());
            m.insert("titles".to_string(), self.titles.to_json());
            Json::Object(m)
        }
    }

    #[test]
    fn test_with() {
        let addr = Address {
            city: "Beijing".to_string(),
            country: "China".to_string(),
        };

        let person = Person {
            name: "Ning Sun".to_string(),
            age: 27,
            addr: addr,
            titles: vec!["programmer".to_string(), "cartographier".to_string()],
        };

        let t0 = Template::compile("{{#with addr}}{{city}}{{/with}}".to_string()).ok().unwrap();
        let t1 = Template::compile("{{#with notfound}}hello{{else}}world{{/with}}".to_string())
                     .ok()
                     .unwrap();
        let t2 = Template::compile("{{#with addr/country}}{{this}}{{/with}}".to_string())
                     .ok()
                     .unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);
        handlebars.register_template("t2", t2);

        let r0 = handlebars.render("t0", &person);
        assert_eq!(r0.ok().unwrap(), "Beijing".to_string());

        let r1 = handlebars.render("t1", &person);
        assert_eq!(r1.ok().unwrap(), "world".to_string());

        let r2 = handlebars.render("t2", &person);
        assert_eq!(r2.ok().unwrap(), "China".to_string());
    }

    #[test]
    fn test_with_block_param() {
        let addr = Address {
            city: "Beijing".to_string(),
            country: "China".to_string(),
        };

        let person = Person {
            name: "Ning Sun".to_string(),
            age: 27,
            addr: addr,
            titles: vec!["programmer".to_string(), "cartographier".to_string()],
        };

        let t0 = Template::compile("{{#with addr as |a|}}{{a.city}}{{/with}}".to_string())
                     .ok()
                     .unwrap();
        let t1 = Template::compile("{{#with notfound as |c|}}hello{{else}}world{{/with}}"
                                       .to_string())
                     .ok()
                     .unwrap();
        let t2 = Template::compile("{{#with addr/country as |t|}}{{t}}{{/with}}".to_string())
                     .ok()
                     .unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);
        handlebars.register_template("t2", t2);

        let r0 = handlebars.render("t0", &person);
        assert_eq!(r0.ok().unwrap(), "Beijing".to_string());

        let r1 = handlebars.render("t1", &person);
        assert_eq!(r1.ok().unwrap(), "world".to_string());

        let r2 = handlebars.render("t2", &person);
        assert_eq!(r2.ok().unwrap(), "China".to_string());
    }

    #[test]
    fn test_with_in_each() {
        let addr = Address {
            city: "Beijing".to_string(),
            country: "China".to_string(),
        };

        let person = Person {
            name: "Ning Sun".to_string(),
            age: 27,
            addr: addr,
            titles: vec!["programmer".to_string(), "cartographier".to_string()],
        };

        let addr2 = Address {
            city: "Beijing".to_string(),
            country: "China".to_string(),
        };

        let person2 = Person {
            name: "Ning Sun".to_string(),
            age: 27,
            addr: addr2,
            titles: vec!["programmer".to_string(), "cartographier".to_string()],
        };

        let people = vec![person, person2];

        let t0 = Template::compile("{{#each this}}{{#with addr}}{{city}}{{/with}}{{/each}}"
                                       .to_string())
                     .ok()
                     .unwrap();
        let t1 = Template::compile("{{#each this}}{{#with addr}}{{../age}}{{/with}}{{/each}}"
                                       .to_string())
                     .ok()
                     .unwrap();
        let t2 = Template::compile("{{#each this}}{{#with addr}}{{@../index}}{{/with}}{{/each}}"
                                       .to_string())
                     .ok()
                     .unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);
        handlebars.register_template("t2", t2);

        let r0 = handlebars.render("t0", &people);
        assert_eq!(r0.ok().unwrap(), "BeijingBeijing".to_string());

        let r1 = handlebars.render("t1", &people);
        assert_eq!(r1.ok().unwrap(), "2727".to_string());

        let r2 = handlebars.render("t2", &people);
        assert_eq!(r2.ok().unwrap(), "01".to_string());
    }
}
<|endoftext|>


<commit_before>use addressable::Addressable;
use addressable::AddressableUtil;
use ram::Ram;

enum Operand {
	Implied,							// OPC				// operand implied
	Immediate(u8),						// OPC #$BB			// operand is byte (BB)
	Accumulator,						// OPC A			// operand is AC
	Relative(i8),						// OPC $BB			// branch target is PC + offset (BB), bit 7 signifies negative offset
	Absolute(u16),						// OPC $HHLL		// operand is address $HHLL
	AbsoluteIndexedWithX(u16),			// OPC $HHLL,X		// operand is address $HHLL incremented by X with carry
	AbsoluteIndexedWithY(u16),			// OPC $HHLL,Y		// operand is address $HHLL incremented by Y with carry
	Indirect(u16),						// OPC ($HHLL)		// operand is effective address; effective address is value of address
	ZeroPage(u8),						// OPC $LL			// operand is address $00LL
	ZeroPageIndexedWithX(u8),			// OPC $LL,X		// operand is address $00LL incremented by X, no page transition
	ZeroPageIndexedWithY(u8),			// OPC $LL,Y		// operand is address $00LL incremented by Y, no page transition
	ZeroPageIndexedWithXIndirect(u8),	// OPC ($LL,X)		// operand is effective address; effective address is $00LL incremented by X without carry
	ZeroPageIndirectIndexedWithY(u8),	// OPC ($LL),Y		// operand is effective address incremented by Y with carry; effective address is word at $00LL
}

impl Operand {
	fn addr (&self, cpu: &CPU) -> u16 {
		match * self {
			Implied								=> fail!("mos6510: Implied operand is never targetted to an address"),
			Immediate(_)						=> fail!("mos6510: Immediade operand is never targetted to an address"),
			Accumulator							=> fail!("mos6510: Accumulator operand is never targetted to an address"),
			Relative(offset)					=> cpu.pc + offset as u16,
			Absolute(addr)						=> addr,
			AbsoluteIndexedWithX(addr)			=> addr + cpu.x as u16,
			AbsoluteIndexedWithY(addr)			=> addr + cpu.y as u16,
			Indirect(addr)						=> cpu.get_le(addr),
			ZeroPage(addr)						=> addr as u16,
			ZeroPageIndexedWithX(addr)			=> (addr + cpu.x) as u16,				// no page transition
			ZeroPageIndexedWithY(addr)			=> (addr + cpu.y) as u16,				// no page transition
			ZeroPageIndexedWithXIndirect(addr)	=> cpu.get_le((addr + cpu.x) as u16),	// no page transition
			ZeroPageIndirectIndexedWithY(addr)	=> { let iaddr: u16 = cpu.get_le(addr as u16); iaddr + cpu.y as u16 },
		}
	}

	fn get (&self, cpu: &CPU) -> u8 {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never has a value"),
			Immediate(val)						=> val,
			Accumulator							=> cpu.ac,
			Relative(_target)					=> fail!("mos6510: Relative operand never has a value"),
			op									=> { let addr = op.addr(cpu); cpu.get(addr) },
		}
	}

	fn set (&self, val: u8, cpu: &mut CPU) {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never sets a value"),
			Immediate(_)						=> fail!("mos6510: Immediate operand never sets a value"),
			Accumulator							=> cpu.ac = val,
			Relative(_target)					=> fail!("mos6510: Relative operand never sets a value"),
			op									=> { let addr = op.addr(cpu); cpu.set(addr, val); },
		}
	}
}

static nmi_vector: u16 = 0xfffa;
static reset_vector: u16 = 0xfffc;
static irq_vector: u16 = 0xfffe;

pub struct CPU {
	pc: u16,				// program counter
	ac: u8,					// accumulator
	x: u8,					// x register
	y: u8,					// y register
	sr: u8,					// status register (NV-BDIZC: Negative, oVerflow, Break, Decimal, Interrupt, Zero, Carry)
	sp: u8,					// stack pointer
	mem: Ram<u16>,
}

impl Addressable<u16> for CPU {
	pub fn get (&self, addr: u16) -> u8 {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.get(addr)
	}

	pub fn set (&mut self, addr: u16, data: u8) {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.set(addr, data);
	}
}

impl CPU {
	pub fn new () -> CPU {
		CPU { pc: 0, ac: 0, x: 0, y: 0, sr: 0, sp: 0, mem: Ram::new() }
	}
}
<commit_msg>Capitalized jump vector constants<commit_after>use addressable::Addressable;
use addressable::AddressableUtil;
use ram::Ram;

enum Operand {
	Implied,							// OPC				// operand implied
	Immediate(u8),						// OPC #$BB			// operand is byte (BB)
	Accumulator,						// OPC A			// operand is AC
	Relative(i8),						// OPC $BB			// branch target is PC + offset (BB), bit 7 signifies negative offset
	Absolute(u16),						// OPC $HHLL		// operand is address $HHLL
	AbsoluteIndexedWithX(u16),			// OPC $HHLL,X		// operand is address $HHLL incremented by X with carry
	AbsoluteIndexedWithY(u16),			// OPC $HHLL,Y		// operand is address $HHLL incremented by Y with carry
	Indirect(u16),						// OPC ($HHLL)		// operand is effective address; effective address is value of address
	ZeroPage(u8),						// OPC $LL			// operand is address $00LL
	ZeroPageIndexedWithX(u8),			// OPC $LL,X		// operand is address $00LL incremented by X, no page transition
	ZeroPageIndexedWithY(u8),			// OPC $LL,Y		// operand is address $00LL incremented by Y, no page transition
	ZeroPageIndexedWithXIndirect(u8),	// OPC ($LL,X)		// operand is effective address; effective address is $00LL incremented by X without carry
	ZeroPageIndirectIndexedWithY(u8),	// OPC ($LL),Y		// operand is effective address incremented by Y with carry; effective address is word at $00LL
}

impl Operand {
	fn addr (&self, cpu: &CPU) -> u16 {
		match * self {
			Implied								=> fail!("mos6510: Implied operand is never targetted to an address"),
			Immediate(_)						=> fail!("mos6510: Immediade operand is never targetted to an address"),
			Accumulator							=> fail!("mos6510: Accumulator operand is never targetted to an address"),
			Relative(offset)					=> cpu.pc + offset as u16,
			Absolute(addr)						=> addr,
			AbsoluteIndexedWithX(addr)			=> addr + cpu.x as u16,
			AbsoluteIndexedWithY(addr)			=> addr + cpu.y as u16,
			Indirect(addr)						=> cpu.get_le(addr),
			ZeroPage(addr)						=> addr as u16,
			ZeroPageIndexedWithX(addr)			=> (addr + cpu.x) as u16,				// no page transition
			ZeroPageIndexedWithY(addr)			=> (addr + cpu.y) as u16,				// no page transition
			ZeroPageIndexedWithXIndirect(addr)	=> cpu.get_le((addr + cpu.x) as u16),	// no page transition
			ZeroPageIndirectIndexedWithY(addr)	=> { let iaddr: u16 = cpu.get_le(addr as u16); iaddr + cpu.y as u16 },
		}
	}

	fn get (&self, cpu: &CPU) -> u8 {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never has a value"),
			Immediate(val)						=> val,
			Accumulator							=> cpu.ac,
			Relative(_target)					=> fail!("mos6510: Relative operand never has a value"),
			op									=> { let addr = op.addr(cpu); cpu.get(addr) },
		}
	}

	fn set (&self, val: u8, cpu: &mut CPU) {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never sets a value"),
			Immediate(_)						=> fail!("mos6510: Immediate operand never sets a value"),
			Accumulator							=> cpu.ac = val,
			Relative(_target)					=> fail!("mos6510: Relative operand never sets a value"),
			op									=> { let addr = op.addr(cpu); cpu.set(addr, val); },
		}
	}
}

static NMI_VECTOR: u16 = 0xfffa;
static RESET_VECTOR: u16 = 0xfffc;
static IRQ_VECTOR: u16 = 0xfffe;

pub struct CPU {
	pc: u16,				// program counter
	ac: u8,					// accumulator
	x: u8,					// x register
	y: u8,					// y register
	sr: u8,					// status register (NV-BDIZC: Negative, oVerflow, Break, Decimal, Interrupt, Zero, Carry)
	sp: u8,					// stack pointer
	mem: Ram<u16>,
}

impl Addressable<u16> for CPU {
	pub fn get (&self, addr: u16) -> u8 {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.get(addr)
	}

	pub fn set (&mut self, addr: u16, data: u8) {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.set(addr, data);
	}
}

impl CPU {
	pub fn new () -> CPU {
		CPU { pc: 0, ac: 0, x: 0, y: 0, sr: 0, sp: 0, mem: Ram::new() }
	}
}
<|endoftext|>


<commit_before>use addressable::Addressable;
use addressable::AddressableUtil;

#[cfg(test)]
use testmemory::TestMemory;

enum Operand {
	Implied,							// OPC				// operand implied
	Immediate(u8),						// OPC #$BB			// operand is byte (BB)
	Accumulator,						// OPC A			// operand is AC
	Relative(i8),						// OPC $BB			// branch target is PC + offset (BB), bit 7 signifies negative offset
	Absolute(u16),						// OPC $HHLL		// operand is address $HHLL
	AbsoluteIndexedWithX(u16),			// OPC $HHLL,X		// operand is address $HHLL incremented by X with carry
	AbsoluteIndexedWithY(u16),			// OPC $HHLL,Y		// operand is address $HHLL incremented by Y with carry
	Indirect(u16),						// OPC ($HHLL)		// operand is effective address; effective address is value of address
	ZeroPage(u8),						// OPC $LL			// operand is address $00LL
	ZeroPageIndexedWithX(u8),			// OPC $LL,X		// operand is address $00LL incremented by X, no page transition
	ZeroPageIndexedWithY(u8),			// OPC $LL,Y		// operand is address $00LL incremented by Y, no page transition
	ZeroPageIndexedWithXIndirect(u8),	// OPC ($LL,X)		// operand is effective address; effective address is $00LL incremented by X without carry
	ZeroPageIndirectIndexedWithY(u8),	// OPC ($LL),Y		// operand is effective address incremented by Y with carry; effective address is word at $00LL
}

impl Operand {
	fn indirect<M: Addressable<u16>> (mem: &M, addr: u16) -> u16 {
		// Get a little endian u16 from the given address, simulating the 6502 MSB bug
		// (i.e. take values from $c0ff/$c000 instead of $c0ff/$c100)
		let addr1 = (addr & 0xff00) | (addr+1 & 0x00ff);
		mem.get(addr) as u16 | mem.get(addr1) as u16 << 8
	}

	fn addr<M: Addressable<u16>> (&self, cpu: &Mos6502, mem: &M) -> u16 {
		match *self {
			Implied								=> fail!("mos65xx: Implied operand is never targetted to an address"),
			Immediate(_)						=> fail!("mos65xx: Immediate operand is never targetted to an address"),
			Accumulator							=> fail!("mos65xx: Accumulator operand is never targetted to an address"),
			Relative(offset)					=> cpu.pc + offset as u16,
			Absolute(addr)						=> addr,
			AbsoluteIndexedWithX(addr)			=> addr + cpu.x as u16,
			AbsoluteIndexedWithY(addr)			=> addr + cpu.y as u16,
			Indirect(addr)						=> Operand::indirect(mem, addr),
			ZeroPage(addr)						=> addr as u16,
			ZeroPageIndexedWithX(addr)			=> (addr + cpu.x) as u16,						// no page transition
			ZeroPageIndexedWithY(addr)			=> (addr + cpu.y) as u16,						// no page transition
			ZeroPageIndexedWithXIndirect(addr)	=> mem.get_le((addr + cpu.x) as u16),			// no page transition
			ZeroPageIndirectIndexedWithY(addr)	=> { let iaddr: u16 = mem.get_le(addr as u16); iaddr + cpu.y as u16 },
		}
	}

	fn get<M: Addressable<u16>> (&self, cpu: &Mos6502, mem: &M) -> u8 {
		match *self {
			Implied								=> fail!("mos65xx: Implied operand never has a value"),
			Immediate(val)						=> val,
			Accumulator							=> cpu.ac,
			Relative(_target)					=> fail!("mos65xx: Relative operand never has a value"),
			op									=> { let addr = op.addr(cpu, mem); mem.get(addr) },
		}
	}

	fn set<M: Addressable<u16>> (&self, cpu: &mut Mos6502, mem: &mut M, val: u8) {
		match *self {
			Implied								=> fail!("mos65xx: Implied operand never sets a value"),
			Immediate(_)						=> fail!("mos65xx: Immediate operand never sets a value"),
			Accumulator							=> cpu.ac = val,
			Relative(_target)					=> fail!("mos65xx: Relative operand never sets a value"),
			op									=> { let addr = op.addr(cpu, mem); mem.set(addr, val); },
		}
	}
}

// General information on 65xx: http://en.wikipedia.org/wiki/MOS_Technology_6510
// Web simulator and much info: http://e-tradition.net/bytes/6502/
// Good reference and overview: http://www.obelisk.demon.co.uk/index.html
// Processor bugs and caveats : http://www.textfiles.com/apple/6502.bugs.txt

static NMI_VECTOR: u16 = 0xfffa;
static RESET_VECTOR: u16 = 0xfffc;
static IRQ_VECTOR: u16 = 0xfffe;

pub struct Mos6502 {
	priv pc: u16,						// program counter
	priv ac: u8,						// accumulator
	priv x: u8,							// x register
	priv y: u8,							// y register
	priv sr: u8,						// status register (NV-BDIZC: Negative, oVerflow, Break, Decimal, Interrupt, Zero, Carry)
	priv sp: u8,						// stack pointer
}

impl Mos6502 {
	pub fn new () -> Mos6502 {
		Mos6502 { pc: 0, ac: 0, x: 0, y: 0, sr: 0, sp: 0 }
	}

	fn get_opcode<M: Addressable<u16>> (&self, mem: &M) -> u8 {
		mem.get(self.pc)
	}

	fn get_argument<M: Addressable<u16>, T: Int> (&self, mem: &M) -> T {
		mem.get_le(self.pc + 1)
	}

	pub fn step<M: Addressable<u16>> (&mut self, mem: &mut M) -> uint {
		// TODO
		0
	}
}

pub struct Mos6510 {
	priv cpu: Mos6502,						// Core CPU
	priv port_ddr: u8,						// CPU port data direction register
	priv port_dat: u8,						// CPU port data register
}

impl Mos6510 {
	pub fn new () -> Mos6510 {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		Mos6510 { cpu: Mos6502::new(), port_ddr: 0, port_dat: 0 }
	}

	pub fn step<M: Addressable<u16>> (&mut self, mem: &mut M) -> uint {
		self.cpu.step(mem)
	}
}

#[test]
fn test_addressing_modes () {
	let mut cpu = Mos6502 { pc: 0x1337, ac: 0x88, x: 0x11, y: 0x22, sr: 0, sp: 0 };
	let mut mem = TestMemory::new::<u16>();
	// Immediate
	assert_eq!(Immediate(0x55).get(&cpu, &mem), 0x55);
	// Accumulator
	assert_eq!(Accumulator.get(&cpu, &mem), 0x88);
	Accumulator.set(&mut cpu, &mut mem, 0x99); assert_eq!(cpu.ac, 0x99);
	// Relative
	assert_eq!(Relative(0x33).addr(&cpu, &mem), 0x136a);
	assert_eq!(Relative(0x99).addr(&cpu, &mem), 0x12d0);
	// Absolute
	assert_eq!(Absolute(0x0123).addr(&cpu, &mem), 0x0123);
	assert_eq!(Absolute(0x0123).get(&cpu, &mem), 0x24);
	Absolute(0x0123).set(&mut cpu, &mut mem, 0x24);
	// AbsoluteIndexedWithX
	assert_eq!(AbsoluteIndexedWithX(0x0123).addr(&cpu, &mem), 0x0134);
	assert_eq!(AbsoluteIndexedWithX(0x0123).get(&cpu, &mem), 0x35);
	AbsoluteIndexedWithX(0x0123).set(&mut cpu, &mut mem, 0x35);
	// AbsoluteIndexedWithY
	assert_eq!(AbsoluteIndexedWithY(0x0123).addr(&cpu, &mem), 0x0145);
	assert_eq!(AbsoluteIndexedWithY(0x0123).get(&cpu, &mem), 0x46);
	AbsoluteIndexedWithY(0x0123).set(&mut cpu, &mut mem, 0x46);
	// Indirect
	assert_eq!(Indirect(0x0123).addr(&cpu, &mem), 0x2524);
	assert_eq!(Indirect(0x0123).get(&cpu, &mem), 0x49);
	Indirect(0x0123).set(&mut cpu, &mut mem, 0x49);
	// ZeroPage
	assert_eq!(ZeroPage(0x12).addr(&cpu, &mem), 0x0012);
	assert_eq!(ZeroPage(0x12).get(&cpu, &mem), 0x12);
	ZeroPage(0x12).set(&mut cpu, &mut mem, 0x12);
	// ZeroPageIndexedWithX
	assert_eq!(ZeroPageIndexedWithX(0x12).addr(&cpu, &mem), 0x0023);
	assert_eq!(ZeroPageIndexedWithX(0x12).get(&cpu, &mem), 0x23);
	ZeroPageIndexedWithX(0x12).set(&mut cpu, &mut mem, 0x23);
	// ZeroPageIndexedWithY
	assert_eq!(ZeroPageIndexedWithY(0x12).addr(&cpu, &mem), 0x0034);
	assert_eq!(ZeroPageIndexedWithY(0x12).get(&cpu, &mem), 0x34);
	ZeroPageIndexedWithY(0x12).set(&mut cpu, &mut mem, 0x34);
	// ZeroPageIndexedWithXIndirect
	assert_eq!(ZeroPageIndexedWithXIndirect(0x12).addr(&cpu, &mem), 0x2423);
	assert_eq!(ZeroPageIndexedWithXIndirect(0x12).get(&cpu, &mem), 0x47);
	ZeroPageIndexedWithXIndirect(0x12).set(&mut cpu, &mut mem, 0x47);
	// ZeroPageIndirectIndexedWithY
	assert_eq!(ZeroPageIndirectIndexedWithY(0x12).addr(&cpu, &mem), 0x1334);
	assert_eq!(ZeroPageIndirectIndexedWithY(0x12).get(&cpu, &mem), 0x47);
	ZeroPageIndirectIndexedWithY(0x12).set(&mut cpu, &mut mem, 0x47);
}

#[test]
fn test_indirect_addressing_bug () {
	let cpu = Mos6502 { pc: 0x1337, ac: 0x88, x: 0x11, y: 0x22, sr: 0, sp: 0 };
	let mem = TestMemory::new::<u16>();
	// Indirect jump to ($c0ff) will get erroneously address from $c0ff/$c000 instead of $c0ff/$c100
	assert_eq!(Indirect(0xc0ff).addr(&cpu, &mem), 0xc0bf);	// must be $c0bf instead of $c1bf
}
<commit_msg>Added proper CPU reset<commit_after>use addressable::Addressable;
use addressable::AddressableUtil;

#[cfg(test)]
use testmemory::TestMemory;

enum Operand {
	Implied,							// OPC				// operand implied
	Immediate(u8),						// OPC #$BB			// operand is byte (BB)
	Accumulator,						// OPC A			// operand is AC
	Relative(i8),						// OPC $BB			// branch target is PC + offset (BB), bit 7 signifies negative offset
	Absolute(u16),						// OPC $HHLL		// operand is address $HHLL
	AbsoluteIndexedWithX(u16),			// OPC $HHLL,X		// operand is address $HHLL incremented by X with carry
	AbsoluteIndexedWithY(u16),			// OPC $HHLL,Y		// operand is address $HHLL incremented by Y with carry
	Indirect(u16),						// OPC ($HHLL)		// operand is effective address; effective address is value of address
	ZeroPage(u8),						// OPC $LL			// operand is address $00LL
	ZeroPageIndexedWithX(u8),			// OPC $LL,X		// operand is address $00LL incremented by X, no page transition
	ZeroPageIndexedWithY(u8),			// OPC $LL,Y		// operand is address $00LL incremented by Y, no page transition
	ZeroPageIndexedWithXIndirect(u8),	// OPC ($LL,X)		// operand is effective address; effective address is $00LL incremented by X without carry
	ZeroPageIndirectIndexedWithY(u8),	// OPC ($LL),Y		// operand is effective address incremented by Y with carry; effective address is word at $00LL
}

impl Operand {
	fn indirect<M: Addressable<u16>> (mem: &M, addr: u16) -> u16 {
		// Get a little endian u16 from the given address, simulating the 6502 MSB bug
		// (i.e. take values from $c0ff/$c000 instead of $c0ff/$c100)
		let addr1 = (addr & 0xff00) | (addr+1 & 0x00ff);
		mem.get(addr) as u16 | mem.get(addr1) as u16 << 8
	}

	fn addr<M: Addressable<u16>> (&self, cpu: &Mos6502, mem: &M) -> u16 {
		match *self {
			Implied								=> fail!("mos65xx: Implied operand is never targetted to an address"),
			Immediate(_)						=> fail!("mos65xx: Immediate operand is never targetted to an address"),
			Accumulator							=> fail!("mos65xx: Accumulator operand is never targetted to an address"),
			Relative(offset)					=> cpu.pc + offset as u16,
			Absolute(addr)						=> addr,
			AbsoluteIndexedWithX(addr)			=> addr + cpu.x as u16,
			AbsoluteIndexedWithY(addr)			=> addr + cpu.y as u16,
			Indirect(addr)						=> Operand::indirect(mem, addr),
			ZeroPage(addr)						=> addr as u16,
			ZeroPageIndexedWithX(addr)			=> (addr + cpu.x) as u16,						// no page transition
			ZeroPageIndexedWithY(addr)			=> (addr + cpu.y) as u16,						// no page transition
			ZeroPageIndexedWithXIndirect(addr)	=> mem.get_le((addr + cpu.x) as u16),			// no page transition
			ZeroPageIndirectIndexedWithY(addr)	=> { let iaddr: u16 = mem.get_le(addr as u16); iaddr + cpu.y as u16 },
		}
	}

	fn get<M: Addressable<u16>> (&self, cpu: &Mos6502, mem: &M) -> u8 {
		match *self {
			Implied								=> fail!("mos65xx: Implied operand never has a value"),
			Immediate(val)						=> val,
			Accumulator							=> cpu.ac,
			Relative(_target)					=> fail!("mos65xx: Relative operand never has a value"),
			op									=> { let addr = op.addr(cpu, mem); mem.get(addr) },
		}
	}

	fn set<M: Addressable<u16>> (&self, cpu: &mut Mos6502, mem: &mut M, val: u8) {
		match *self {
			Implied								=> fail!("mos65xx: Implied operand never sets a value"),
			Immediate(_)						=> fail!("mos65xx: Immediate operand never sets a value"),
			Accumulator							=> cpu.ac = val,
			Relative(_target)					=> fail!("mos65xx: Relative operand never sets a value"),
			op									=> { let addr = op.addr(cpu, mem); mem.set(addr, val); },
		}
	}
}

// General information on 65xx: http://en.wikipedia.org/wiki/MOS_Technology_6510
// Web simulator and much info: http://e-tradition.net/bytes/6502/
// Good reference and overview: http://www.obelisk.demon.co.uk/index.html
// Processor bugs and caveats : http://www.textfiles.com/apple/6502.bugs.txt

static NMI_VECTOR: u16 = 0xfffa;
static RESET_VECTOR: u16 = 0xfffc;
static IRQ_VECTOR: u16 = 0xfffe;

pub struct Mos6502 {
	priv pc: u16,						// program counter
	priv ac: u8,						// accumulator
	priv x: u8,							// x register
	priv y: u8,							// y register
	priv sr: u8,						// status register (NV-BDIZC: Negative, oVerflow, Break, Decimal, Interrupt, Zero, Carry)
	priv sp: u8,						// stack pointer
}

impl Mos6502 {
	pub fn new () -> Mos6502 {
		Mos6502 { pc: 0, ac: 0, x: 0, y: 0, sr: 0, sp: 0 }
	}

	fn get_opcode<M: Addressable<u16>> (&self, mem: &M) -> u8 {
		mem.get(self.pc)
	}

	fn get_argument<M: Addressable<u16>, T: Int> (&self, mem: &M) -> T {
		mem.get_le(self.pc + 1)
	}

	pub fn reset<M: Addressable<u16>> (&mut self, mem: &M) {
		// On reset, the interrupt-disable flag is set (and the decimal flag is cleared in the CMOS version 65c02).
		// The other bits and all registers (including the stack pointer are unspecified and might contain random values.
		// Execution begins at the address pointed to by the reset vector at address $FFFC.
		debug!("mos65xx: Reset");
		self.pc = mem.get_le(RESET_VECTOR);
		self.sr = 0x24;
	}

	pub fn step<M: Addressable<u16>> (&mut self, mem: &mut M) -> uint {
		// TODO
		0
	}
}

pub struct Mos6510 {
	priv cpu: Mos6502,						// Core CPU
	priv port_ddr: u8,						// CPU port data direction register
	priv port_dat: u8,						// CPU port data register
}

impl Mos6510 {
	pub fn new () -> Mos6510 {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		Mos6510 { cpu: Mos6502::new(), port_ddr: 0, port_dat: 0 }
	}

	pub fn reset<M: Addressable<u16>> (&mut self, mem: &M) {
		self.cpu.reset(mem);
	}

	pub fn step<M: Addressable<u16>> (&mut self, mem: &mut M) -> uint {
		self.cpu.step(mem)
	}
}

#[test]
fn test_addressing_modes () {
	let mut cpu = Mos6502 { pc: 0x1337, ac: 0x88, x: 0x11, y: 0x22, sr: 0, sp: 0 };
	let mut mem = TestMemory::new::<u16>();
	// Immediate
	assert_eq!(Immediate(0x55).get(&cpu, &mem), 0x55);
	// Accumulator
	assert_eq!(Accumulator.get(&cpu, &mem), 0x88);
	Accumulator.set(&mut cpu, &mut mem, 0x99); assert_eq!(cpu.ac, 0x99);
	// Relative
	assert_eq!(Relative(0x33).addr(&cpu, &mem), 0x136a);
	assert_eq!(Relative(0x99).addr(&cpu, &mem), 0x12d0);
	// Absolute
	assert_eq!(Absolute(0x0123).addr(&cpu, &mem), 0x0123);
	assert_eq!(Absolute(0x0123).get(&cpu, &mem), 0x24);
	Absolute(0x0123).set(&mut cpu, &mut mem, 0x24);
	// AbsoluteIndexedWithX
	assert_eq!(AbsoluteIndexedWithX(0x0123).addr(&cpu, &mem), 0x0134);
	assert_eq!(AbsoluteIndexedWithX(0x0123).get(&cpu, &mem), 0x35);
	AbsoluteIndexedWithX(0x0123).set(&mut cpu, &mut mem, 0x35);
	// AbsoluteIndexedWithY
	assert_eq!(AbsoluteIndexedWithY(0x0123).addr(&cpu, &mem), 0x0145);
	assert_eq!(AbsoluteIndexedWithY(0x0123).get(&cpu, &mem), 0x46);
	AbsoluteIndexedWithY(0x0123).set(&mut cpu, &mut mem, 0x46);
	// Indirect
	assert_eq!(Indirect(0x0123).addr(&cpu, &mem), 0x2524);
	assert_eq!(Indirect(0x0123).get(&cpu, &mem), 0x49);
	Indirect(0x0123).set(&mut cpu, &mut mem, 0x49);
	// ZeroPage
	assert_eq!(ZeroPage(0x12).addr(&cpu, &mem), 0x0012);
	assert_eq!(ZeroPage(0x12).get(&cpu, &mem), 0x12);
	ZeroPage(0x12).set(&mut cpu, &mut mem, 0x12);
	// ZeroPageIndexedWithX
	assert_eq!(ZeroPageIndexedWithX(0x12).addr(&cpu, &mem), 0x0023);
	assert_eq!(ZeroPageIndexedWithX(0x12).get(&cpu, &mem), 0x23);
	ZeroPageIndexedWithX(0x12).set(&mut cpu, &mut mem, 0x23);
	// ZeroPageIndexedWithY
	assert_eq!(ZeroPageIndexedWithY(0x12).addr(&cpu, &mem), 0x0034);
	assert_eq!(ZeroPageIndexedWithY(0x12).get(&cpu, &mem), 0x34);
	ZeroPageIndexedWithY(0x12).set(&mut cpu, &mut mem, 0x34);
	// ZeroPageIndexedWithXIndirect
	assert_eq!(ZeroPageIndexedWithXIndirect(0x12).addr(&cpu, &mem), 0x2423);
	assert_eq!(ZeroPageIndexedWithXIndirect(0x12).get(&cpu, &mem), 0x47);
	ZeroPageIndexedWithXIndirect(0x12).set(&mut cpu, &mut mem, 0x47);
	// ZeroPageIndirectIndexedWithY
	assert_eq!(ZeroPageIndirectIndexedWithY(0x12).addr(&cpu, &mem), 0x1334);
	assert_eq!(ZeroPageIndirectIndexedWithY(0x12).get(&cpu, &mem), 0x47);
	ZeroPageIndirectIndexedWithY(0x12).set(&mut cpu, &mut mem, 0x47);
}

#[test]
fn test_indirect_addressing_bug () {
	let cpu = Mos6502 { pc: 0x1337, ac: 0x88, x: 0x11, y: 0x22, sr: 0, sp: 0 };
	let mem = TestMemory::new::<u16>();
	// Indirect jump to ($c0ff) will get erroneously address from $c0ff/$c000 instead of $c0ff/$c100
	assert_eq!(Indirect(0xc0ff).addr(&cpu, &mem), 0xc0bf);	// must be $c0bf instead of $c1bf
}
<|endoftext|>


<commit_before>//! The kind traits

#[lang="const"]
pub trait Const {
    // Empty.
}

#[lang="copy"]
pub trait Copy {
    // Empty.
}

#[lang="send"]
pub trait Send {
    // Empty.
}

#[lang="owned"]
pub trait Owned {
    // Empty.
}
<commit_msg>core: Add docs about kind traits<commit_after>/*!
The kind traits

Rust types can be classified in vairous useful ways according to
intrinsic properties of the type. These classifications, often called
'kinds', are represented as traits.

They cannot be implemented by user code, but are instead implemented
by the compiler automatically for the types to which they apply.

The 4 kinds are

* Copy - types that may be copied without allocation. This includes
  scalar types and managed pointers, and exludes owned pointers. It
  also excludes types that implement `Drop`.

* Send - owned types and types containing owned types.  These types
  may be transferred across task boundaries.

* Const - types that are deeply immutable. Const types are used for
  freezable data structures.

* Owned - types that do not contain borrowed pointers. Note that this
  meaning of 'owned' conflicts with 'owned pointers'. The two notions
  of ownership are different.

`Copy` types include both implicitly copyable types that the compiler
will copy automatically and non-implicitly copyable types that require
the `copy` keyword to copy. Types that do not implement `Copy` may
instead implement `Clone`.

*/

#[lang="copy"]
pub trait Copy {
    // Empty.
}

#[lang="send"]
pub trait Send {
    // Empty.
}

#[lang="const"]
pub trait Const {
    // Empty.
}

#[lang="owned"]
pub trait Owned {
    // Empty.
}
<|endoftext|>