<commit_before>use Itertools;
use std::cmp;
use std::cell::{Cell, RefCell};
use std::mem;
use std::vec;

struct GroupInner<K, I, F>
    where I: Iterator,
{
    key: F,
    iter: I,
    current_key: Option<K>,
    current_elt: Option<I::Item>,
    // buffering stuff
    done: bool,
    /// Index of group we are currently buffering or visiting
    top: usize,
    /// Least index for which we still have elements buffered
    bot: usize,

    /// Buffered groups, from `bot` (index 0) to `top`.
    buffer: Vec<vec::IntoIter<I::Item>>,
    /// index of last group iter that was dropped
    dropped_group: Option<usize>,
}

impl<K, I, F> GroupInner<K, I, F>
    where I: Iterator,
          F: FnMut(&I::Item) -> K,
          K: PartialEq,
{
    fn push_next_group(&mut self, group: Vec<I::Item>) {
        // When we add a new buffered group, fill up slots between bot and top
        while self.top - self.bot > self.buffer.len() {
            if self.buffer.is_empty() {
                self.bot += 1;
            } else {
                self.buffer.push(Vec::new().into_iter());
            }
        }
        self.buffer.push(group.into_iter());
        debug_assert!(self.top + 1 - self.bot == self.buffer.len());
    }
    /// `client`: Index of group that requests next element
    fn step(&mut self, client: usize) -> Option<I::Item> {
        /*
        println!("client={}, bot={}, top={}, buffers={:?}",
                 client, self.bot, self.top,
                 self.buffer.iter().map(|x| x.len()).collect::<Vec<_>>());
         */
        if client < self.bot {
            None
        } else if client < self.top ||
            (client == self.top && self.buffer.len() > self.top - self.bot)
        {
            // if `bufidx` doesn't exist in self.buffer, it might be empty
            let bufidx = client - self.bot;
            let elt = self.buffer.get_mut(bufidx).and_then(|queue| queue.next());
            if elt.is_none() {
                // FIXME: Use a smarter way to reuse the vector space
                // VecDeque is unfortunately not zero allocation when empty.
                while self.buffer.len() > 0 && self.buffer[0].len() == 0 {
                    self.buffer.remove(0);
                    self.bot += 1;
                }
            }
            elt
        } else if self.done {
            return None;
        } else if self.top == client {
            self.step_current()
        } else {
            // requested a later group -- walk through all groups up to
            // the requested group index, and buffer the elements (unless
            // the group is marked as dropped).
            let mut group = Vec::new();

            if let Some(elt) = self.current_elt.take() {
                if self.dropped_group != Some(self.top) {
                    group.push(elt);
                }
            }
            loop {
                match self.iter.next() {
                    None => {
                        if self.dropped_group != Some(self.top) {
                            self.push_next_group(group);
                        }
                        self.done = true;
                        return None;
                    }
                    Some(elt) => {
                        let key = (self.key)(&elt);
                        match self.current_key.take() {
                            None => {}
                            Some(old_key) => if old_key != key {
                                if self.dropped_group != Some(self.top) {
                                    self.push_next_group(mem::replace(&mut group, Vec::new()));
                                }
                                self.top += 1;
                                if self.top == client {
                                    self.current_key = Some(key);
                                    return Some(elt);
                                }
                            },
                        }
                        self.current_key = Some(key);
                        if self.dropped_group != Some(self.top) {
                            group.push(elt);
                        }
                    }
                }
            }
        }
    }

    /// This is the immediate case, where we use no buffering
    fn step_current(&mut self) -> Option<I::Item> {
        debug_assert!(!self.done);
        if let elt @ Some(..) = self.current_elt.take() {
            return elt;
        }
        match self.iter.next() {
            None => {
                self.done = true;
                return None;
            }
            Some(elt) => {
                let key = (self.key)(&elt);
                match self.current_key.take() {
                    None => {}
                    Some(old_key) => if old_key != key {
                        self.current_key = Some(key);
                        self.current_elt = Some(elt);
                        self.top += 1;
                        return None;
                    },
                }
                self.current_key = Some(key);
                Some(elt)
            }
        }
    }

    /// Request the just started groups' key.
    ///
    /// `client`: Index of group
    ///
    /// **Panics** if no group key is available.
    fn group_key(&mut self, client: usize) -> K {
        // This can only be called after we have just returned the first
        // element of a group.
        // Perform this by simply buffering one more element, grabbing the
        // next key.
        debug_assert!(!self.done);
        debug_assert!(client == self.top);
        debug_assert!(self.current_key.is_some());
        debug_assert!(self.current_elt.is_none());
        match self.iter.next() {
            None => {
                self.done = true;
                self.current_key.take().unwrap()
            }
            Some(elt) => {
                let key = (self.key)(&elt);
                match self.current_key.take() {
                    None => unreachable!(),
                    Some(old_key) => {
                        if old_key != key {
                            self.top += 1;
                        }
                        self.current_key = Some(key);
                        self.current_elt = Some(elt);
                        old_key
                    }
                }
            }
        }
    }
}

impl<K, I, F> GroupInner<K, I, F>
    where I: Iterator,
{
    /// Called when a group is dropped
    fn drop_group(&mut self, client: usize) {
        // It's only useful to track the highest index
        self.dropped_group = Some(cmp::max(client,
                                           self.dropped_group.unwrap_or(0)));
    }
}

/// `GroupByLazy` is the storage for the lazy grouping operation.
///
/// If the groups are consumed in their original order, or if each
/// group is dropped without keeping it around, then `GroupByLazy` uses
/// no allocations. It needs allocations only if several group iterators
/// are alive at the same time.
///
/// This type implements `IntoIterator` (it is **not** an iterator
/// itself), because the group iterators need to borrow from this
/// value. It should stored in a local variable or temporary and
/// iterated.
///
/// See [`.group_by_lazy()`](trait.Itertools.html#method.group_by_lazy) for more information.
pub struct GroupByLazy<K, I, F>
    where I: Iterator,
{
    inner: RefCell<GroupInner<K, I, F>>,
    // the group iterator's current index. Keep this in the main value
    // so that simultaneous iterators all use the same state.
    index: Cell<usize>,
}

/// Create a new
pub fn new<K, J, F>(iter: J, f: F) -> GroupByLazy<K, J::IntoIter, F>
    where J: IntoIterator,
          F: FnMut(&J::Item) -> K,
{
    GroupByLazy {
        inner: RefCell::new(GroupInner {
            key: f,
            iter: iter.into_iter(),
            current_key: None,
            current_elt: None,
            done: false,
            top: 0,
            bot: 0,
            buffer: Vec::new(),
            dropped_group: None,
        }),
        index: Cell::new(0),
    }
}

impl<K, I, F> GroupByLazy<K, I, F>
    where I: Iterator,
{
    /// `client`: Index of group that requests next element
    fn step(&self, client: usize) -> Option<I::Item>
        where F: FnMut(&I::Item) -> K,
              K: PartialEq,
    {
        self.inner.borrow_mut().step(client)
    }

    /// `client`: Index of group that requests next element
    fn group_key(&self, client: usize) -> K
        where F: FnMut(&I::Item) -> K,
              K: PartialEq,
    {
        self.inner.borrow_mut().group_key(client)
    }

    /// `client`: Index of group
    fn drop_group(&self, client: usize) {
        self.inner.borrow_mut().drop_group(client)
    }
}

impl<'a, K, I, F> IntoIterator for &'a GroupByLazy<K, I, F>
    where I: Iterator,
          I::Item: 'a,
          F: FnMut(&I::Item) -> K,
          K: PartialEq,
{
    type Item = (K, Group<'a, K, I, F>);
    type IntoIter = Groups<'a, K, I, F>;

    fn into_iter(self) -> Self::IntoIter {
        Groups {
            parent: self,
        }
    }
}

/// An iterator that yields the Group iterators.
///
/// Iterator element type is `(K, Group)`:
/// the group's key `K` and the group's iterator.
pub struct Groups<'a, K: 'a, I: 'a, F: 'a>
    where I: Iterator,
          I::Item: 'a,
{
    parent: &'a GroupByLazy<K, I, F>,
}

impl<'a, K, I, F> Iterator for Groups<'a, K, I, F>
    where I: Iterator,
          I::Item: 'a,
          F: FnMut(&I::Item) -> K,
          K: PartialEq,
{
    type Item = (K, Group<'a, K, I, F>);

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        let index = self.parent.index.get();
        self.parent.index.set(index + 1);
        self.parent.step(index).map(|elt| {
            let key = self.parent.group_key(index);
            (key, Group {
                parent: self.parent,
                index: index,
                first: Some(elt),
            })
        })
    }
}

/// An iterator for the elements in a single group.
///
/// Iterator element type is `I::Item`.
pub struct Group<'a, K: 'a, I: 'a, F: 'a>
    where I: Iterator,
          I::Item: 'a,
{
    parent: &'a GroupByLazy<K, I, F>,
    index: usize,
    first: Option<I::Item>,
}

impl<'a, K, I, F> Drop for Group<'a, K, I, F>
    where I: Iterator,
          I::Item: 'a,
{
    fn drop(&mut self) {
        self.parent.drop_group(self.index);
    }
}

impl<'a, K, I, F> Iterator for Group<'a, K, I, F>
    where I: Iterator,
          I::Item: 'a,
          F: FnMut(&I::Item) -> K,
          K: PartialEq,
{
    type Item = I::Item;
    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if let elt @ Some(..) = self.first.take() {
            return elt;
        }
        self.parent.step(self.index)
    }
}
<commit_msg>groupbylazy: Code cleanup<commit_after>use Itertools;
use std::cmp;
use std::cell::{Cell, RefCell};
use std::vec;

struct GroupInner<K, I, F>
    where I: Iterator,
{
    key: F,
    iter: I,
    current_key: Option<K>,
    current_elt: Option<I::Item>,
    /// flag set if iterator is exhausted
    done: bool,
    /// Index of group we are currently buffering or visiting
    top: usize,
    /// Least index for which we still have elements buffered
    bot: usize,
    /// Buffered groups, from `bot` (index 0) to `top`.
    buffer: Vec<vec::IntoIter<I::Item>>,
    /// index of last group iter that was dropped
    dropped_group: Option<usize>,
}

impl<K, I, F> GroupInner<K, I, F>
    where I: Iterator,
          F: FnMut(&I::Item) -> K,
          K: PartialEq,
{
    fn push_next_group(&mut self, group: Vec<I::Item>) {
        // When we add a new buffered group, fill up slots between bot and top
        while self.top - self.bot > self.buffer.len() {
            if self.buffer.is_empty() {
                self.bot += 1;
            } else {
                self.buffer.push(Vec::new().into_iter());
            }
        }
        self.buffer.push(group.into_iter());
        debug_assert!(self.top + 1 - self.bot == self.buffer.len());
    }

    /// Take the next element from the iterator, and set the done
    /// flag if exhausted. Must not be called after done.
    fn next_element(&mut self) -> Option<I::Item> {
        debug_assert!(!self.done);
        match self.iter.next() {
            None => { self.done = true; None }
            otherwise => otherwise,
        }
    }

    /// `client`: Index of group that requests next element
    fn step(&mut self, client: usize) -> Option<I::Item> {
        /*
        println!("client={}, bot={}, top={}, buffers=[{}]",
                 client, self.bot, self.top,
                 self.buffer.iter().format(", ", |elt, f| f(&elt.len())));
         */
        if client < self.bot {
            None
        } else if client < self.top ||
            (client == self.top && self.buffer.len() > self.top - self.bot)
        {
            // if `bufidx` doesn't exist in self.buffer, it might be empty
            let bufidx = client - self.bot;
            let elt = self.buffer.get_mut(bufidx).and_then(|queue| queue.next());
            if elt.is_none() {
                // FIXME: Use a smarter way to reuse the vector space
                // VecDeque is unfortunately not zero allocation when empty.
                while self.buffer.len() > 0 && self.buffer[0].len() == 0 {
                    self.buffer.remove(0);
                    self.bot += 1;
                }
            }
            elt
        } else if self.done {
            return None;
        } else if self.top == client {
            self.step_current()
        } else {
            // requested a later group -- walk through the current group up to
            // the requested group index, and buffer the elements (unless
            // the group is marked as dropped).
            // Because the `Groups` iterator is always the first to request
            // each group index, client is the next index efter top.
            debug_assert!(self.top + 1 == client);
            let mut group = Vec::new();

            if let Some(elt) = self.current_elt.take() {
                if self.dropped_group != Some(self.top) {
                    group.push(elt);
                }
            }
            let mut first_elt = None; // first element of the next group

            while let Some(elt) = self.next_element() {
                let key = (self.key)(&elt);
                match self.current_key.take() {
                    None => {}
                    Some(old_key) => if old_key != key {
                        self.current_key = Some(key);
                        first_elt = Some(elt);
                        break;
                    },
                }
                self.current_key = Some(key);
                if self.dropped_group != Some(self.top) {
                    group.push(elt);
                }
            }

            if self.dropped_group != Some(self.top) {
                self.push_next_group(group);
            }
            if first_elt.is_some() {
                self.top += 1;
                debug_assert!(self.top == client);
            }
            first_elt
        }
    }

    /// This is the immediate case, where we use no buffering
    fn step_current(&mut self) -> Option<I::Item> {
        debug_assert!(!self.done);
        if let elt @ Some(..) = self.current_elt.take() {
            return elt;
        }
        match self.next_element() {
            None => None,
            Some(elt) => {
                let key = (self.key)(&elt);
                match self.current_key.take() {
                    None => {}
                    Some(old_key) => if old_key != key {
                        self.current_key = Some(key);
                        self.current_elt = Some(elt);
                        self.top += 1;
                        return None;
                    },
                }
                self.current_key = Some(key);
                Some(elt)
            }
        }
    }

    /// Request the just started groups' key.
    ///
    /// `client`: Index of group
    ///
    /// **Panics** if no group key is available.
    fn group_key(&mut self, client: usize) -> K {
        // This can only be called after we have just returned the first
        // element of a group.
        // Perform this by simply buffering one more element, grabbing the
        // next key.
        debug_assert!(!self.done);
        debug_assert!(client == self.top);
        debug_assert!(self.current_key.is_some());
        debug_assert!(self.current_elt.is_none());
        let old_key = self.current_key.take().unwrap();
        if let Some(elt) = self.next_element() {
            let key = (self.key)(&elt);
            if old_key != key {
                self.top += 1;
            }
            self.current_key = Some(key);
            self.current_elt = Some(elt);
        }
        old_key
    }
}

impl<K, I, F> GroupInner<K, I, F>
    where I: Iterator,
{
    /// Called when a group is dropped
    fn drop_group(&mut self, client: usize) {
        // It's only useful to track the highest index
        self.dropped_group = Some(cmp::max(client,
                                           self.dropped_group.unwrap_or(0)));
    }
}

/// `GroupByLazy` is the storage for the lazy grouping operation.
///
/// If the groups are consumed in their original order, or if each
/// group is dropped without keeping it around, then `GroupByLazy` uses
/// no allocations. It needs allocations only if several group iterators
/// are alive at the same time.
///
/// This type implements `IntoIterator` (it is **not** an iterator
/// itself), because the group iterators need to borrow from this
/// value. It should stored in a local variable or temporary and
/// iterated.
///
/// See [`.group_by_lazy()`](trait.Itertools.html#method.group_by_lazy) for more information.
pub struct GroupByLazy<K, I, F>
    where I: Iterator,
{
    inner: RefCell<GroupInner<K, I, F>>,
    // the group iterator's current index. Keep this in the main value
    // so that simultaneous iterators all use the same state.
    index: Cell<usize>,
}

/// Create a new
pub fn new<K, J, F>(iter: J, f: F) -> GroupByLazy<K, J::IntoIter, F>
    where J: IntoIterator,
          F: FnMut(&J::Item) -> K,
{
    GroupByLazy {
        inner: RefCell::new(GroupInner {
            key: f,
            iter: iter.into_iter(),
            current_key: None,
            current_elt: None,
            done: false,
            top: 0,
            bot: 0,
            buffer: Vec::new(),
            dropped_group: None,
        }),
        index: Cell::new(0),
    }
}

impl<K, I, F> GroupByLazy<K, I, F>
    where I: Iterator,
{
    /// `client`: Index of group that requests next element
    fn step(&self, client: usize) -> Option<I::Item>
        where F: FnMut(&I::Item) -> K,
              K: PartialEq,
    {
        self.inner.borrow_mut().step(client)
    }

    /// `client`: Index of group that requests next element
    fn group_key(&self, client: usize) -> K
        where F: FnMut(&I::Item) -> K,
              K: PartialEq,
    {
        self.inner.borrow_mut().group_key(client)
    }

    /// `client`: Index of group
    fn drop_group(&self, client: usize) {
        self.inner.borrow_mut().drop_group(client)
    }
}

impl<'a, K, I, F> IntoIterator for &'a GroupByLazy<K, I, F>
    where I: Iterator,
          I::Item: 'a,
          F: FnMut(&I::Item) -> K,
          K: PartialEq,
{
    type Item = (K, Group<'a, K, I, F>);
    type IntoIter = Groups<'a, K, I, F>;

    fn into_iter(self) -> Self::IntoIter {
        Groups {
            parent: self,
        }
    }
}

/// An iterator that yields the Group iterators.
///
/// Iterator element type is `(K, Group)`:
/// the group's key `K` and the group's iterator.
pub struct Groups<'a, K: 'a, I: 'a, F: 'a>
    where I: Iterator,
          I::Item: 'a,
{
    parent: &'a GroupByLazy<K, I, F>,
}

impl<'a, K, I, F> Iterator for Groups<'a, K, I, F>
    where I: Iterator,
          I::Item: 'a,
          F: FnMut(&I::Item) -> K,
          K: PartialEq,
{
    type Item = (K, Group<'a, K, I, F>);

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        let index = self.parent.index.get();
        self.parent.index.set(index + 1);
        self.parent.step(index).map(|elt| {
            let key = self.parent.group_key(index);
            (key, Group {
                parent: self.parent,
                index: index,
                first: Some(elt),
            })
        })
    }
}

/// An iterator for the elements in a single group.
///
/// Iterator element type is `I::Item`.
pub struct Group<'a, K: 'a, I: 'a, F: 'a>
    where I: Iterator,
          I::Item: 'a,
{
    parent: &'a GroupByLazy<K, I, F>,
    index: usize,
    first: Option<I::Item>,
}

impl<'a, K, I, F> Drop for Group<'a, K, I, F>
    where I: Iterator,
          I::Item: 'a,
{
    fn drop(&mut self) {
        self.parent.drop_group(self.index);
    }
}

impl<'a, K, I, F> Iterator for Group<'a, K, I, F>
    where I: Iterator,
          I::Item: 'a,
          F: FnMut(&I::Item) -> K,
          K: PartialEq,
{
    type Item = I::Item;
    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if let elt @ Some(..) = self.first.take() {
            return elt;
        }
        self.parent.step(self.index)
    }
}
<|endoftext|>


<commit_before>use ast::*;
use std::collections::HashMap;
use std::io;
use std::io::prelude::*;

#[derive(Debug, PartialEq, Clone)]
pub enum Value {
    Nil,
    Boolean(bool),
    Number(f64),
    String(String),
}

impl Value {
    fn is_true(&self) -> bool {
        match *self {
            Value::Nil => false,
            Value::Boolean(b) => b,
            _ => true,
        }
    }

    fn to_string(&self) -> String {
        match *self {
            Value::Nil => "nil".into(),
            Value::Boolean(ref b) => b.to_string(),
            Value::Number(ref n) => n.to_string(),
            Value::String(ref s) => s.clone(),
        }
    }
}

struct Environment {
    values: HashMap<Identifier, Value>,
}

impl Environment {
    fn new() -> Environment {
        Environment { values: HashMap::new() }
    }

    fn define(&mut self, identifier: Identifier, value: Value) {
        // NOTE that this allow for variable redefinition. See the chapter.
        self.values.insert(identifier, value);
    }

    // The signature is a bit weird, but saves a clone on every assignment
    fn try_set(&mut self, identifier: Identifier, value: Value) -> Option<Identifier> {
        if self.values.contains_key(&identifier) {
            self.values.insert(identifier, value);
            None
        } else {
            Some(identifier)
        }
    }

    fn get(&self, identifier: &Identifier) -> Option<&Value> {
        self.values.get(identifier)
    }
}

pub trait Interpreter {
    fn execute(&mut self, statement: &Statement) -> Result<Option<Value>, RuntimeError>;
}

pub struct StatementInterpreter {
    environment: Environment,
}

impl StatementInterpreter {
    pub fn new() -> StatementInterpreter {
        StatementInterpreter { environment: Environment::new() }
    }
}
impl Interpreter for StatementInterpreter {
    fn execute(&mut self, statement: &Statement) -> Result<Option<Value>, RuntimeError> {
        statement.execute(&mut self.environment)
    }
}

#[derive(Debug)]
pub enum RuntimeError {
    UnaryMinusTypeMismatch(Value),
    BinaryOperatorTypeMismatch(BinaryOperator, Value, Value),
    UndefinedIdentifier(Identifier),
}

trait Interpret {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError>;
}

trait Execute {
    fn execute(&self, environment: &mut Environment) -> Result<Option<Value>, RuntimeError>;
}

impl Interpret for Expr {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        match *self {
            Expr::Literal(ref l) => l.interpret(environment),
            Expr::Unary(ref u) => u.interpret(environment),
            Expr::Binary(ref b) => b.interpret(environment),
            Expr::Grouping(ref g) => g.interpret(environment),
            Expr::Identifier(ref i) => i.interpret(environment),
            Expr::Assignment(ref a) => a.interpret(environment),
        }
    }
}

impl Interpret for Literal {
    fn interpret(&self, _: &mut Environment) -> Result<Value, RuntimeError> {
        match *self {
            Literal::NilLiteral => Ok(Value::Nil),
            Literal::BoolLiteral(b) => Ok(Value::Boolean(b)),
            Literal::StringLiteral(ref s) => Ok(Value::String(s.clone())),
            Literal::NumberLiteral(n) => Ok(Value::Number(n)),
        }
    }
}

impl Interpret for Identifier {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        match environment.get(self) {
            Some(value) => Ok(value.clone()),
            None => Err(RuntimeError::UndefinedIdentifier(self.clone())),
        }
    }
}

impl Interpret for Assignment {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        let target = match self.lvalue {
            Target::Identifier(ref i) => Identifier { name: i.name.clone() },
        };
        match self.rvalue.interpret(environment) {
            Ok(value) => {
                match environment.try_set(target, value.clone()) {
                    None => Ok(value.clone()),
                    Some(target) => Err(RuntimeError::UndefinedIdentifier(target))
                }
            }
            Err(error) => Err(error),
        }
    }
}

impl Interpret for Grouping {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        self.expr.interpret(environment)
    }
}

impl Interpret for UnaryExpr {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        let value = try!(self.right.interpret(environment));
        match self.operator {
            UnaryOperator::Bang => Ok(Value::Boolean(!value.is_true())),
            UnaryOperator::Minus => {
                match value {
                    Value::Number(n) => Ok(Value::Number(-n)),
                    _ => Err(RuntimeError::UnaryMinusTypeMismatch(value)),
                }
            }
        }
    }
}

impl Interpret for BinaryExpr {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        let left = try!(self.left.interpret(environment));
        let right = try!(self.right.interpret(environment));
        match (&self.operator, &left, &right) {
            (&BinaryOperator::Minus, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Number(l - r))
            }
            (&BinaryOperator::Slash, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Number(l / r))
            }
            (&BinaryOperator::Star, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Number(l * r))
            }
            (&BinaryOperator::Plus, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Number(l + r))
            }
            (&BinaryOperator::Plus, &Value::String(ref l), &Value::String(ref r)) => {
                let mut result = String::new();
                result.push_str(l);
                result.push_str(r);
                Ok(Value::String(result))
            }
            (&BinaryOperator::Greater, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Boolean(l > r))
            }
            (&BinaryOperator::Less, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Boolean(l < r))
            }
            (&BinaryOperator::GreaterEqual, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Boolean(l >= r))
            }
            (&BinaryOperator::LessEqual, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Boolean(l <= r))
            }
            (&BinaryOperator::NotEqual, l, r) => Ok(Value::Boolean(l != r)),
            (&BinaryOperator::Equal, l, r) => Ok(Value::Boolean(l == r)),
            _ => {
                Err(RuntimeError::BinaryOperatorTypeMismatch(self.operator,
                                                             left.clone(),
                                                             right.clone()))
            }
        }
    }
}

impl Execute for Statement {
    fn execute(&self, mut environment: &mut Environment) -> Result<Option<Value>, RuntimeError> {
        match *self {
            Statement::Expression(ref e) => e.interpret(environment).map(Some),
            Statement::Print(ref e) => {
                e.interpret(environment).map(|value| {
                    println!("{}", value.to_string());
                    let _ = io::stdout().flush(); //TODO: is this okay?
                    None
                })
            }
            Statement::VariableDefinition(ref identifier) => {
                let identifier = Identifier { name: identifier.name.clone() };
                environment.define(identifier, Value::Nil);
                Ok(None)
            }
            Statement::VariableDefinitionWithInitalizer(ref identifier, ref expression) => {
                let identifier = Identifier { name: identifier.name.clone() };
                expression.interpret(environment).map(|initializer| {
                    environment.define(identifier, initializer);
                    None
                })
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use ast::*;
    use interpreter::{Interpret, Environment, Value};

    #[test]
    fn literal() {
        let mut environment = Environment::new();
        let string = String::from("abc");
        let expr = Expr::Literal(Literal::StringLiteral(string.clone()));
        assert_eq!(Value::String(string),
                   expr.interpret(&mut environment).unwrap());
    }

    #[test]
    fn grouping() {
        let mut environment = Environment::new();
        let expr = Grouping { expr: Expr::Literal(Literal::NumberLiteral(45.67f64)) };
        assert_eq!(Value::Number(45.67f64),
                   expr.interpret(&mut environment).unwrap());
    }

    #[test]
    fn unary() {
        let mut environment = Environment::new();
        let expr = UnaryExpr {
            operator: UnaryOperator::Bang,
            right: Expr::Literal(Literal::BoolLiteral(false)),
        };
        assert_eq!(Value::Boolean(true),
                   expr.interpret(&mut environment).unwrap());
    }

    #[test]
    fn binary() {
        let mut environment = Environment::new();
        let expr = BinaryExpr {
            operator: BinaryOperator::Plus,
            left: Expr::Literal(Literal::NumberLiteral(1.0f64)),
            right: Expr::Literal(Literal::NumberLiteral(1.0f64)),
        };
        assert_eq!(Value::Number(2.0f64),
                   expr.interpret(&mut environment).unwrap());
    }

}
<commit_msg>Support for nested environments<commit_after>use ast::*;
use std::collections::HashMap;
use std::io;
use std::io::prelude::*;

#[derive(Debug, PartialEq, Clone)]
pub enum Value {
    Nil,
    Boolean(bool),
    Number(f64),
    String(String),
}

impl Value {
    fn is_true(&self) -> bool {
        match *self {
            Value::Nil => false,
            Value::Boolean(b) => b,
            _ => true,
        }
    }

    fn to_string(&self) -> String {
        match *self {
            Value::Nil => "nil".into(),
            Value::Boolean(ref b) => b.to_string(),
            Value::Number(ref n) => n.to_string(),
            Value::String(ref s) => s.clone(),
        }
    }
}

struct Environment {
    enclosing: Option<Box<Environment>>,
    values: HashMap<Identifier, Value>,
}

impl Environment {
    fn new() -> Environment {
        Environment {
            values: HashMap::new(),
            enclosing: None,
        }
    }

    fn new_with_parent(environment: Environment) -> Environment {
        Environment {
            values: HashMap::new(),
            enclosing: Some(Box::new(environment)),
        }
    }

    fn define(&mut self, identifier: Identifier, value: Value) {
        // NOTE that this allow for variable redefinition. See the chapter.
        self.values.insert(identifier, value);
    }

    // The signature is a bit weird, but saves a clone on every assignment
    fn try_set(&mut self, identifier: Identifier, value: Value) -> Option<Identifier> {
        if self.values.contains_key(&identifier) {
            self.values.insert(identifier, value);
            None
        } else {
            match self.enclosing {
                None => Some(identifier),
                Some(ref mut enclosing) => enclosing.try_set(identifier, value),
            }
        }
    }

    fn get(&self, identifier: &Identifier) -> Option<&Value> {
        match self.values.get(identifier) {
            None => {
                match self.enclosing {
                    None => None,
                    Some(ref enclosing) => enclosing.get(identifier),
                }
            }
            value => value,
        }
    }
}

pub trait Interpreter {
    fn execute(&mut self, statement: &Statement) -> Result<Option<Value>, RuntimeError>;
}

pub struct StatementInterpreter {
    environment: Environment,
}

impl StatementInterpreter {
    pub fn new() -> StatementInterpreter {
        StatementInterpreter { environment: Environment::new() }
    }
}
impl Interpreter for StatementInterpreter {
    fn execute(&mut self, statement: &Statement) -> Result<Option<Value>, RuntimeError> {
        statement.execute(&mut self.environment)
    }
}

#[derive(Debug)]
pub enum RuntimeError {
    UnaryMinusTypeMismatch(Value),
    BinaryOperatorTypeMismatch(BinaryOperator, Value, Value),
    UndefinedIdentifier(Identifier),
}

trait Interpret {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError>;
}

trait Execute {
    fn execute(&self, environment: &mut Environment) -> Result<Option<Value>, RuntimeError>;
}

impl Interpret for Expr {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        match *self {
            Expr::Literal(ref l) => l.interpret(environment),
            Expr::Unary(ref u) => u.interpret(environment),
            Expr::Binary(ref b) => b.interpret(environment),
            Expr::Grouping(ref g) => g.interpret(environment),
            Expr::Identifier(ref i) => i.interpret(environment),
            Expr::Assignment(ref a) => a.interpret(environment),
        }
    }
}

impl Interpret for Literal {
    fn interpret(&self, _: &mut Environment) -> Result<Value, RuntimeError> {
        match *self {
            Literal::NilLiteral => Ok(Value::Nil),
            Literal::BoolLiteral(b) => Ok(Value::Boolean(b)),
            Literal::StringLiteral(ref s) => Ok(Value::String(s.clone())),
            Literal::NumberLiteral(n) => Ok(Value::Number(n)),
        }
    }
}

impl Interpret for Identifier {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        match environment.get(self) {
            Some(value) => Ok(value.clone()),
            None => Err(RuntimeError::UndefinedIdentifier(self.clone())),
        }
    }
}

impl Interpret for Assignment {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        let target = match self.lvalue {
            Target::Identifier(ref i) => Identifier { name: i.name.clone() },
        };
        match self.rvalue.interpret(environment) {
            Ok(value) => {
                match environment.try_set(target, value.clone()) {
                    None => Ok(value.clone()),
                    Some(target) => Err(RuntimeError::UndefinedIdentifier(target)),
                }
            }
            Err(error) => Err(error),
        }
    }
}

impl Interpret for Grouping {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        self.expr.interpret(environment)
    }
}

impl Interpret for UnaryExpr {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        let value = try!(self.right.interpret(environment));
        match self.operator {
            UnaryOperator::Bang => Ok(Value::Boolean(!value.is_true())),
            UnaryOperator::Minus => {
                match value {
                    Value::Number(n) => Ok(Value::Number(-n)),
                    _ => Err(RuntimeError::UnaryMinusTypeMismatch(value)),
                }
            }
        }
    }
}

impl Interpret for BinaryExpr {
    fn interpret(&self, environment: &mut Environment) -> Result<Value, RuntimeError> {
        let left = try!(self.left.interpret(environment));
        let right = try!(self.right.interpret(environment));
        match (&self.operator, &left, &right) {
            (&BinaryOperator::Minus, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Number(l - r))
            }
            (&BinaryOperator::Slash, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Number(l / r))
            }
            (&BinaryOperator::Star, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Number(l * r))
            }
            (&BinaryOperator::Plus, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Number(l + r))
            }
            (&BinaryOperator::Plus, &Value::String(ref l), &Value::String(ref r)) => {
                let mut result = String::new();
                result.push_str(l);
                result.push_str(r);
                Ok(Value::String(result))
            }
            (&BinaryOperator::Greater, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Boolean(l > r))
            }
            (&BinaryOperator::Less, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Boolean(l < r))
            }
            (&BinaryOperator::GreaterEqual, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Boolean(l >= r))
            }
            (&BinaryOperator::LessEqual, &Value::Number(l), &Value::Number(r)) => {
                Ok(Value::Boolean(l <= r))
            }
            (&BinaryOperator::NotEqual, l, r) => Ok(Value::Boolean(l != r)),
            (&BinaryOperator::Equal, l, r) => Ok(Value::Boolean(l == r)),
            _ => {
                Err(RuntimeError::BinaryOperatorTypeMismatch(self.operator,
                                                             left.clone(),
                                                             right.clone()))
            }
        }
    }
}

impl Execute for Statement {
    fn execute(&self, mut environment: &mut Environment) -> Result<Option<Value>, RuntimeError> {
        match *self {
            Statement::Expression(ref e) => e.interpret(environment).map(Some),
            Statement::Print(ref e) => {
                e.interpret(environment).map(|value| {
                    println!("{}", value.to_string());
                    let _ = io::stdout().flush(); //TODO: is this okay?
                    None
                })
            }
            Statement::VariableDefinition(ref identifier) => {
                let identifier = Identifier { name: identifier.name.clone() };
                environment.define(identifier, Value::Nil);
                Ok(None)
            }
            Statement::VariableDefinitionWithInitalizer(ref identifier, ref expression) => {
                let identifier = Identifier { name: identifier.name.clone() };
                expression.interpret(environment).map(|initializer| {
                    environment.define(identifier, initializer);
                    None
                })
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use ast::*;
    use interpreter::{Interpret, Environment, Value};

    #[test]
    fn literal() {
        let mut environment = Environment::new();
        let string = String::from("abc");
        let expr = Expr::Literal(Literal::StringLiteral(string.clone()));
        assert_eq!(Value::String(string),
                   expr.interpret(&mut environment).unwrap());
    }

    #[test]
    fn grouping() {
        let mut environment = Environment::new();
        let expr = Grouping { expr: Expr::Literal(Literal::NumberLiteral(45.67f64)) };
        assert_eq!(Value::Number(45.67f64),
                   expr.interpret(&mut environment).unwrap());
    }

    #[test]
    fn unary() {
        let mut environment = Environment::new();
        let expr = UnaryExpr {
            operator: UnaryOperator::Bang,
            right: Expr::Literal(Literal::BoolLiteral(false)),
        };
        assert_eq!(Value::Boolean(true),
                   expr.interpret(&mut environment).unwrap());
    }

    #[test]
    fn binary() {
        let mut environment = Environment::new();
        let expr = BinaryExpr {
            operator: BinaryOperator::Plus,
            left: Expr::Literal(Literal::NumberLiteral(1.0f64)),
            right: Expr::Literal(Literal::NumberLiteral(1.0f64)),
        };
        assert_eq!(Value::Number(2.0f64),
                   expr.interpret(&mut environment).unwrap());
    }

}
<|endoftext|>


<commit_before>
use ir;
use lang::{Module,Function,Block};
use std;

// TODO: check that each Register has only one user

macro_rules! condition {
    ($cond:expr, $msg:expr) => {
        if !($cond) {
            return Err($msg.into());
        }
    }
}

/// The result of verification.
pub type Result = std::result::Result<(),String>;

/// Verifies the well-formedness of a module.
pub fn verify(module: &ir::Module) -> Result {

    for func in module.functions() {
        try!(self::verify_function(module, func));
    }

    Ok(())
}

/// Verifies that a function is well-formed.
pub fn verify_function(module: &ir::Module,
                       func: &ir::Function) -> Result {

    try!(util::verify_ident(func.name()));

    condition!(func.blocks().next().is_some(),
               "every function must have at least one basic block");

    for block in func.blocks() {
        try!(self::verify_block(module, block));

        condition!(func.blocks().filter(|a| a.name() == block.name()).count() == 1,
                   "basic blocks must have unique names for each function");
    }

    Ok(())
}

/// Verifies that a block is well-formed.
pub fn verify_block(module: &ir::Module,
                    block: &ir::Block) -> Result {

    use lang::Value;

    try!(util::verify_ident(block.name()));

    for value in block.values() {
        // TODO: only the last instruction in a block can be a terminator.

        try!(self::verify_value(module, value.expression()));

        condition!(value.ty().is_void(),
                   "all top-level values must be of type void");
    }

    if let Some(value) = block.values().last() {
        condition!(value.is_terminator(),
                   "every basic block must end with a terminating instruction");
    } else { // block is empty
        return Err("there must be at least one instruction in a basic block".into());
    }

    Ok(())
}

/// Verifies that a value is well-formed.
pub fn verify_value(module: &ir::Module,
                    value: &ir::Expression) -> Result {
    match *value {
        ir::Expression::Instruction(ref val) => values::instruction(module, val),
        _ => Ok(()),
    }
}

mod values
{
    use ir::{Module,Instruction};
    use super::Result;

    pub fn instruction(module: &Module,
                       inst: &Instruction) -> Result
    {
        match *inst {
            Instruction::Call(ref i) => instruction::call(module, i),
            Instruction::Break(ref i) => instruction::br(module, i),
            Instruction::Return(ref i) => instruction::ret(module, i),
            Instruction::Add(ref i) => instruction::binary_arith(module,i),
            Instruction::Sub(ref i) => instruction::binary_arith(module,i),
            Instruction::Mul(ref i) => instruction::binary_arith(module,i),
            Instruction::Div(ref i) => instruction::binary_arith(module,i),
            Instruction::Shl(ref i) => instruction::binary_arith(module,i),
            Instruction::Shr(ref i) => instruction::binary_arith(module,i),
        }
    }

    pub mod instruction
    {
        use ir::{Module,instruction};
        use super::super::Result;

        // TODO: check that arguments are the same in type and number
        pub fn call(_module: &Module,
                    inst: &instruction::Call) -> Result {

            condition!(inst.target().expression().is_function_ref(),
                       "call instructions must refer to functions");

            Ok(())
        }

        // TODO: check that the referenced block is in the same function
        // as the instruction.
        pub fn br(_module: &Module,
                  inst: &instruction::Break) -> Result {

            condition!(inst.target().expression().is_block_ref(),
                       "break instructions must refer to basic blocks");

            Ok(())
        }

        // TODO: check that the type is consistent with the function.
        pub fn ret(_module: &Module,
                   _inst: &instruction::Return) -> Result {

            Ok(())
        }

        pub fn binary_arith<I>(_module: &Module,
                               inst: &I) -> Result
            where I: instruction::Binary {

            let (lhs,rhs) = inst.operands();

            condition!(lhs.ty() == rhs.ty(),
                       format!("binary arithmetic operations must have operands of the same type"));
            Ok(())
        }
    }
}

/// Utility methods.
mod util
{
    use super::Result;

    /// Checks if an identifier is valid.
    pub fn verify_ident(ident: &str) -> Result
    {
        let maybe_first_char = ident.chars().next();

        let first_char = match maybe_first_char {
            Some(c) => c,
            None => return Err("identifier cannot be empty".into()),
        };

        condition!(first_char.is_alphabetic() || first_char == '_',
                   "identifier must start with an alphabetic character or _");

        let valid = ident.chars().all(|c| c.is_alphanumeric() || c == '_');

        if valid {
            Ok(())
        } else {
            Err("identifier can only contain alphanumeric characters or numbers".into())
        }
    }
}
<commit_msg>Renamed 'value' to 'expression' in ir::verifier<commit_after>
use ir;
use lang::{Module,Function,Block};
use std;

// TODO: check that each Register has only one user

macro_rules! condition {
    ($cond:expr, $msg:expr) => {
        if !($cond) {
            return Err($msg.into());
        }
    }
}

/// The result of verification.
pub type Result = std::result::Result<(),String>;

/// Verifies the well-formedness of a module.
pub fn verify(module: &ir::Module) -> Result {

    for func in module.functions() {
        try!(self::verify_function(module, func));
    }

    Ok(())
}

/// Verifies that a function is well-formed.
pub fn verify_function(module: &ir::Module,
                       func: &ir::Function) -> Result {

    try!(util::verify_ident(func.name()));

    condition!(func.blocks().next().is_some(),
               "every function must have at least one basic block");

    for block in func.blocks() {
        try!(self::verify_block(module, block));

        condition!(func.blocks().filter(|a| a.name() == block.name()).count() == 1,
                   "basic blocks must have unique names for each function");
    }

    Ok(())
}

/// Verifies that a block is well-formed.
pub fn verify_block(module: &ir::Module,
                    block: &ir::Block) -> Result {

    use lang::Value;

    try!(util::verify_ident(block.name()));

    for value in block.values() {
        // TODO: only the last instruction in a block can be a terminator.

        try!(self::verify_value(module, value));

        condition!(value.ty().is_void(),
                   "all top-level values must be of type void");
    }

    if let Some(value) = block.values().last() {
        condition!(value.is_terminator(),
                   "every basic block must end with a terminating instruction");
    } else { // block is empty
        return Err("there must be at least one instruction in a basic block".into());
    }

    Ok(())
}

/// Verifies that a value is well-formed.
pub fn verify_value(module: &ir::Module,
                    value: &ir::Value) -> Result {
    verify_expression(module, value.expression())
}

/// Verifies that an expression is well-formed.
pub fn verify_expression(module: &ir::Module,
                         expr: &ir::Expression) -> Result {
    match *expr {
        ir::Expression::Instruction(ref val) => values::instruction(module, val),
        _ => Ok(()),
    }
}

mod values
{
    use ir::{Module,Instruction};
    use super::Result;

    pub fn instruction(module: &Module,
                       inst: &Instruction) -> Result
    {
        match *inst {
            Instruction::Call(ref i) => instruction::call(module, i),
            Instruction::Break(ref i) => instruction::br(module, i),
            Instruction::Return(ref i) => instruction::ret(module, i),
            Instruction::Add(ref i) => instruction::binary_arith(module,i),
            Instruction::Sub(ref i) => instruction::binary_arith(module,i),
            Instruction::Mul(ref i) => instruction::binary_arith(module,i),
            Instruction::Div(ref i) => instruction::binary_arith(module,i),
            Instruction::Shl(ref i) => instruction::binary_arith(module,i),
            Instruction::Shr(ref i) => instruction::binary_arith(module,i),
        }
    }

    pub mod instruction
    {
        use ir::{Module,instruction};
        use super::super::Result;

        // TODO: check that arguments are the same in type and number
        pub fn call(_module: &Module,
                    inst: &instruction::Call) -> Result {

            condition!(inst.target().expression().is_function_ref(),
                       "call instructions must refer to functions");

            Ok(())
        }

        // TODO: check that the referenced block is in the same function
        // as the instruction.
        pub fn br(_module: &Module,
                  inst: &instruction::Break) -> Result {

            condition!(inst.target().expression().is_block_ref(),
                       "break instructions must refer to basic blocks");

            Ok(())
        }

        // TODO: check that the type is consistent with the function.
        pub fn ret(_module: &Module,
                   _inst: &instruction::Return) -> Result {

            Ok(())
        }

        pub fn binary_arith<I>(_module: &Module,
                               inst: &I) -> Result
            where I: instruction::Binary {

            let (lhs,rhs) = inst.operands();

            condition!(lhs.ty() == rhs.ty(),
                       format!("binary arithmetic operations must have operands of the same type"));
            Ok(())
        }
    }
}

/// Utility methods.
mod util
{
    use super::Result;

    /// Checks if an identifier is valid.
    pub fn verify_ident(ident: &str) -> Result
    {
        let maybe_first_char = ident.chars().next();

        let first_char = match maybe_first_char {
            Some(c) => c,
            None => return Err("identifier cannot be empty".into()),
        };

        condition!(first_char.is_alphabetic() || first_char == '_',
                   "identifier must start with an alphabetic character or _");

        let valid = ident.chars().all(|c| c.is_alphanumeric() || c == '_');

        if valid {
            Ok(())
        } else {
            Err("identifier can only contain alphanumeric characters or numbers".into())
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use middle::ty;

use syntax::ast::*;
use syntax::oldvisit;

#[deriving(Clone)]
pub struct Context {
    in_loop: bool,
    can_ret: bool
}

pub fn check_crate(tcx: ty::ctxt, crate: &Crate) {
    oldvisit::visit_crate(crate,
                          (Context { in_loop: false, can_ret: true },
                          oldvisit::mk_vt(@oldvisit::Visitor {
        visit_item: |i, (_cx, v)| {
            oldvisit::visit_item(i, (Context {
                                    in_loop: false,
                                    can_ret: true
                                 }, v));
        },
        visit_expr: |e: @expr, (cx, v): (Context, oldvisit::vt<Context>)| {
            match e.node {
              expr_while(e, ref b) => {
                (v.visit_expr)(e, (cx, v));
                (v.visit_block)(b, (Context { in_loop: true,.. cx }, v));
              }
              expr_loop(ref b, _) => {
                (v.visit_block)(b, (Context { in_loop: true,.. cx }, v));
              }
              expr_fn_block(_, ref b) => {
                (v.visit_block)(b, (Context {
                                         in_loop: false,
                                         can_ret: false
                                      }, v));
              }
              expr_break(_) => {
                if !cx.in_loop {
                    tcx.sess.span_err(e.span, "`break` outside of loop");
                }
              }
              expr_again(_) => {
                if !cx.in_loop {
                    tcx.sess.span_err(e.span, "`again` outside of loop");
                }
              }
              expr_ret(oe) => {
                if !cx.can_ret {
                    tcx.sess.span_err(e.span, "`return` in block function");
                }
                oldvisit::visit_expr_opt(oe, (cx, v));
              }
              _ => oldvisit::visit_expr(e, (cx, v))
            }
        },
        .. *oldvisit::default_visitor()
    })));
}
<commit_msg>auto merge of #8292 : thestinger/rust/fix_loop_warning, r=brson<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use middle::ty;

use syntax::ast::*;
use syntax::oldvisit;

#[deriving(Clone)]
pub struct Context {
    in_loop: bool,
    can_ret: bool
}

pub fn check_crate(tcx: ty::ctxt, crate: &Crate) {
    oldvisit::visit_crate(crate,
                          (Context { in_loop: false, can_ret: true },
                          oldvisit::mk_vt(@oldvisit::Visitor {
        visit_item: |i, (_cx, v)| {
            oldvisit::visit_item(i, (Context {
                                    in_loop: false,
                                    can_ret: true
                                 }, v));
        },
        visit_expr: |e: @expr, (cx, v): (Context, oldvisit::vt<Context>)| {
            match e.node {
              expr_while(e, ref b) => {
                (v.visit_expr)(e, (cx, v));
                (v.visit_block)(b, (Context { in_loop: true,.. cx }, v));
              }
              expr_loop(ref b, _) => {
                (v.visit_block)(b, (Context { in_loop: true,.. cx }, v));
              }
              expr_fn_block(_, ref b) => {
                (v.visit_block)(b, (Context {
                                         in_loop: false,
                                         can_ret: false
                                      }, v));
              }
              expr_break(_) => {
                if !cx.in_loop {
                    tcx.sess.span_err(e.span, "`break` outside of loop");
                }
              }
              expr_again(_) => {
                if !cx.in_loop {
                    tcx.sess.span_err(e.span, "`loop` outside of loop");
                }
              }
              expr_ret(oe) => {
                if !cx.can_ret {
                    tcx.sess.span_err(e.span, "`return` in block function");
                }
                oldvisit::visit_expr_opt(oe, (cx, v));
              }
              _ => oldvisit::visit_expr(e, (cx, v))
            }
        },
        .. *oldvisit::default_visitor()
    })));
}
<|endoftext|>


<commit_before>/*!
Macro to declare lazily evaluated statics, which allows runtime initialization.

The macro works by defining a custom type with a `Deref` impl, which delegates the dereferencing
to a hidden `static mut` that gets lazily initialized on first access.

# Examples

To load the extension and use it:

```rust,ignore

}
```
*/

#![crate_id = "lazy_static"]
#![crate_type = "dylib"]
#![license = "MIT"]

#![feature(macro_rules)]

#[macro_export]
macro_rules! lazy_static {
    ($(static ref $N:ident : $T:ty = $e:expr;)*) => {
        $(
            #[allow(non_camel_case_types)]
            #[allow(dead_code)]
            struct $N {__unit__: ()}
            static $N: $N = $N {__unit__: ()};
            impl Deref<$T> for $N {
                fn deref<'a>(&'a self) -> &'a $T {
                    use std::sync::{Once, ONCE_INIT};
                    use std::mem::transmute;

                    #[inline(always)]
                    fn require_share<T: Share>(_: &T) { }

                    unsafe {
                        static mut s: *$T = 0 as *$T;
                        static mut ONCE: Once = ONCE_INIT;
                        ONCE.doit(|| {
                            s = transmute::<Box<$T>, *$T>(box() ($e));
                        });
                        let static_ref = &*s;
                        require_share(static_ref);
                        static_ref
                    }
                }
            }

        )*
    }
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;

    lazy_static! {
        static ref NUMBER: uint = times_two(3);
        static ref VEC: [Box<uint>, ..3] = [box 1, box 2, box 3];
        static ref OWNED_STRING: String = "hello".to_string();
        static ref HASHMAP: HashMap<uint, &'static str> = {
            let mut m = HashMap::new();
            m.insert(0u, "abc");
            m.insert(1, "def");
            m.insert(2, "ghi");
            m
        };
        static ref UNUSED: () = ();
    }

    fn times_two(n: uint) -> uint {
        n * 2
    }

    #[test]
    fn test_basic() {
        assert_eq!(OWNED_STRING.as_slice(), "hello");
        assert_eq!(*NUMBER, 6);
        assert!(HASHMAP.find(&1).is_some());
        assert!(HASHMAP.find(&3).is_none());
        assert_eq!(VEC.as_slice(), &[box 1, box 2, box 3]);
    }

    #[test]
    fn test_repeat() {
        assert_eq!(*NUMBER, 6);
        assert_eq!(*NUMBER, 6);
        assert_eq!(*NUMBER, 6);
    }
}
<commit_msg>Add Docs<commit_after>/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```
lazy_static! {
    static ref NAME_1: TYPE_1 = EXPR_1;
    static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    static ref NAME_N: TYPE_N = EXPR_N;
}
```

# Semantic

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a
unique type that implements `Deref<TYPE>` and stores it in a static with name `NAME`.

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.

Like regular `static mut`s, this macro only works for types that fulfill the `Share`
trait.

# Example

Using the macro:

```rust
#![feature(phase)]

#[phase(plugin)]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<uint, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0u, "foo");
        m.insert(1u, "bar");
        m.insert(2u, "baz");
        m
    };
    static ref COUNT: uint = HASHMAP.len();
    static ref NUMBER: uint = times_two(21);
}

fn times_two(n: uint) -> uint { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0));
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden `static mut` that is guarded by a atomic check
using the `sync::Once` abstraction. All lazily evaluated values are currently
put in a heap allocated box, due to the Rust language currently not providing any way to
define uninitialized `static mut` values.

*/

#![crate_id = "lazy_static"]
#![crate_type = "dylib"]
#![license = "MIT"]

#![feature(macro_rules)]

#[macro_export]
macro_rules! lazy_static {
    ($(static ref $N:ident : $T:ty = $e:expr;)*) => {
        $(
            #[allow(non_camel_case_types)]
            #[allow(dead_code)]
            struct $N {__unit__: ()}
            static $N: $N = $N {__unit__: ()};
            impl Deref<$T> for $N {
                fn deref<'a>(&'a self) -> &'a $T {
                    use std::sync::{Once, ONCE_INIT};
                    use std::mem::transmute;

                    #[inline(always)]
                    fn require_share<T: Share>(_: &T) { }

                    unsafe {
                        static mut s: *$T = 0 as *$T;
                        static mut ONCE: Once = ONCE_INIT;
                        ONCE.doit(|| {
                            s = transmute::<Box<$T>, *$T>(box() ($e));
                        });
                        let static_ref = &*s;
                        require_share(static_ref);
                        static_ref
                    }
                }
            }

        )*
    }
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;

    lazy_static! {
        static ref NUMBER: uint = times_two(3);
        static ref VEC: [Box<uint>, ..3] = [box 1, box 2, box 3];
        static ref OWNED_STRING: String = "hello".to_string();
        static ref HASHMAP: HashMap<uint, &'static str> = {
            let mut m = HashMap::new();
            m.insert(0u, "abc");
            m.insert(1, "def");
            m.insert(2, "ghi");
            m
        };
        static ref UNUSED: () = ();
    }

    fn times_two(n: uint) -> uint {
        n * 2
    }

    #[test]
    fn test_basic() {
        assert_eq!(OWNED_STRING.as_slice(), "hello");
        assert_eq!(*NUMBER, 6);
        assert!(HASHMAP.find(&1).is_some());
        assert!(HASHMAP.find(&3).is_none());
        assert_eq!(VEC.as_slice(), &[box 1, box 2, box 3]);
    }

    #[test]
    fn test_repeat() {
        assert_eq!(*NUMBER, 6);
        assert_eq!(*NUMBER, 6);
        assert_eq!(*NUMBER, 6);
    }
}
<|endoftext|>


<commit_before>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};

static IP: &'static str = "127.0.0.1";
static PORT:        int = 4414;
static mut count:   int = 0;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {
					println(format!("Received connection from: [{:s}]", pn.to_str()));
					unsafe {
						count = count + 1;
						println!("Total number of requests received: {:d}", count)
					}
				},
                                None => ()
                             }
                           },
                None => ()
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);
            println(format!("Received request :\n{:s}", request_str));
            unsafe {
            let response: ~str =
                 ("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

" + format!("Total Number of Requests: {:d}
", count) +
                 "\r\n");
            stream.write(response.as_bytes());
            }
            println!("Connection terminates.");
        }
    }
}
<commit_msg>Server can now serve up files<commit_after>//
// zhttpto.rs
//
// Starting code for PS1
// Running on Rust 0.9
//
// Note that this code has serious security risks!  You should not run it
// on any system with access to sensitive files.
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu and David Evans
// Version 0.3

#[feature(globs)];
use std::io::*;
use std::io::net::ip::{SocketAddr};
use std::{str};

static IP: &'static str = "127.0.0.1";
static PORT:        int = 4414;
static mut count:   int = 0;

fn main() {
    let addr = from_str::<SocketAddr>(format!("{:s}:{:d}", IP, PORT)).unwrap();
    let mut acceptor = net::tcp::TcpListener::bind(addr).listen();

    println(format!("Listening on [{:s}] ...", addr.to_str()));

    for stream in acceptor.incoming() {
        // Spawn a task to handle the connection
        do spawn {
            let mut stream = stream;

            match stream {
                Some(ref mut s) => {
                             match s.peer_name() {
                                Some(pn) => {
					println(format!("Received connection from: [{:s}]", pn.to_str()));
					unsafe {
						count = count + 1;
						println!("Total number of requests received: {:d}", count)
					}
				},
                                None => ()
                             }
                           },
                None => ()
            }

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);
            println(format!("Received request :\n{:s}", request_str));
            let mut components : ~[~str] = ~[];
            for tempString in request_str.split(' ') {
            	components.push(tempString.to_owned());
            }
            if !str::eq(&components[1], &~"/") {
        	let f1name = components[1].slice_from(1);
        	let path1 = Path::new(f1name.clone());
        	let mut msg_file1 = File::open(&path1);
                let msg_bytes1: ~[u8] = msg_file1.read_to_end();
		stream.write(msg_bytes1);
            }
            else {
            unsafe {
            let response: ~str =
                 ("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

" + format!("Total Number of Requests: {:d}
", count) +
                 "\r\n");
            stream.write(response.as_bytes());
            }
            println!("Connection terminates.");
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::sync::{Arc, RwLock};
use std::option::Option;
use std::clone::Clone;

use uuid::Uuid;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

#[derive(Clone)]
pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

pub struct CellFormat {
    pub fieldname: String,
    pub fieldtype: CellType
}

pub struct RecFormat {
    pub cols: Vec<CellFormat>
}

impl RecFormat {
    pub fn new(fields: Vec<CellFormat>) -> Arc<RwLock<RecFormat>> {
        return Arc::new(RwLock::new(RecFormat { cols: fields } ));
    }
}

/*
trait Formattable {
    fn own_format(&mut self) {
        self.format = RecFormat::new(self.format.cols);
    }
}
*/

pub struct Rec {
    pub guid: Uuid,
    pub cells: Vec<CellType>,
    pub format: Arc<RwLock<RecFormat>>
}

impl Rec {
    pub fn new(format: Arc<RwLock<RecFormat>>) -> Rec {
        let cells = format
                        .read()
                        .unwrap()
                        .cols
                        .iter()
                        .map(|x| x.type_.clone()).collect::<Vec<CellType>>();
        return Rec { guid: Uuid::new_v4(),
                     cells: cells,
                     format: format
                   };
    }
}

/*
impl Formattable for Rec {
}
*/

pub struct Table {
    pub name: Option<String>,
    pub rows: Vec<Rec>,
    pub format: Arc<RwLock<RecFormat>>
}

impl Table {
    pub fn new(format: Arc<RwLock<RecFormat>>) -> Table {
        return Table {
            format: format,
            name: None,
            rows: Vec::new()
        };
    }
}
<commit_msg>Fix misstyping<commit_after>use std::sync::{Arc, RwLock};
use std::option::Option;
use std::clone::Clone;

use uuid::Uuid;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

#[derive(Clone)]
pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

pub struct CellFormat {
    pub fieldname: String,
    pub fieldtype: CellType
}

pub struct RecFormat {
    pub cols: Vec<CellFormat>
}

impl RecFormat {
    pub fn new(fields: Vec<CellFormat>) -> Arc<RwLock<RecFormat>> {
        return Arc::new(RwLock::new(RecFormat { cols: fields } ));
    }
}

/*
trait Formattable {
    fn own_format(&mut self) {
        self.format = RecFormat::new(self.format.cols);
    }
}
*/

pub struct Rec {
    pub guid: Uuid,
    pub cells: Vec<CellType>,
    pub format: Arc<RwLock<RecFormat>>
}

impl Rec {
    pub fn new(format: Arc<RwLock<RecFormat>>) -> Rec {
        let cells = format
                        .read()
                        .unwrap()
                        .cols
                        .iter()
                        .map(|x| x.fieldtype.clone()).collect::<Vec<CellType>>();
        return Rec { guid: Uuid::new_v4(),
                     cells: cells,
                     format: format
                   };
    }
}

/*
impl Formattable for Rec {
}
*/

pub struct Table {
    pub name: Option<String>,
    pub rows: Vec<Rec>,
    pub format: Arc<RwLock<RecFormat>>
}

impl Table {
    pub fn new(format: Arc<RwLock<RecFormat>>) -> Table {
        return Table {
            format: format,
            name: None,
            rows: Vec::new()
        };
    }
}
<|endoftext|>


<commit_before>extern crate extra;

use std::env;
use std::fs::File;
use std::io;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::process::exit;

static MAN_PAGE: &str = /* @MANSTART{grep} */ r#"
NAME
    grep - print lines matching a pattern

SYNOPSIS
    grep [-h | --help] [-n --line-number] PATTERN [FILE...]

DESCRIPTION
    grep searches the named input FILEs for lines containing a match to the given PATTERN. If no
    files are specified, grep searches the standard input. grep prints the matching lines.

OPTIONS
    -h
    --help
        Print this manual page.

    -v
    --invert-match
        Invert matching.

    -c
    --count
        Print count of matching lines, instead of those lines.

    -n
    --line-number
        Prefix each line of output with the line number of the match.
"#; /* @MANEND */

#[derive(Copy, Clone)]
struct Flags {
    line_numbers: bool,
    invert_match: bool,
    count: bool,
}

impl Flags {
    fn new() -> Flags {
        Flags {
            line_numbers: false,
            invert_match: false,
            count: false,
        }
    }
}

fn main() {
    let args = env::args().skip(1);
    let stdin = io::stdin();
    let stdin = stdin.lock();

    let mut flags = Flags::new();
    let mut pattern = String::new();
    let mut files = Vec::with_capacity(args.len());
    for arg in args {
        if arg.starts_with('-') {
            match arg.as_str() {
                "-h" | "--help" => {
                    print!("{}", MAN_PAGE);
                    exit(0);
                }
                "-n" | "--line-number" => flags.line_numbers = true,
                "-v" | "--invert-match" => flags.invert_match = true,
                "-c" | "--count" => flags.count = true,
                _ => {
                    eprintln!("Error, unknown option: {}", arg);
                    exit(2);
                }
            }
        } else if pattern.is_empty() {
            pattern = arg.clone();
        } else {
            files.push(arg)
        }
    }

    if pattern.is_empty() {
        eprintln!("You must provide a pattern");
        exit(2);
    }

    let mut found = false;
    let mut error = false;
    if files.is_empty() {
        found = do_simple_search(BufReader::new(stdin), &pattern, flags);
    } else {
        for path in files {
            match File::open(&Path::new(&path)) {
                Ok(f) => {
                    found |= do_simple_search(BufReader::new(f), &pattern, flags);
                }
                Err(err) => {
                    eprintln!("Error opening {}: {}", path, err);
                    error = true;
                }
            }
        }
    }
    if error {
        exit(2);
    }
    if !found {
        exit(1);
    }
}

fn do_simple_search<T: BufRead>(reader: T, pattern: &str, flags: Flags) -> bool {
    let mut count = 0;
    for (line_num, result) in reader.lines().enumerate() {
        if let Ok(line) = result {
            let mut is_match = line.contains(pattern);
            if flags.invert_match {
                is_match = !is_match
            }
            if is_match {
                count += 1;
                if !flags.count {
                    if flags.line_numbers {
                        print!("{}: ", line_num + 1);
                    }
                    println!("{}", line);
                }
            }
        }
    }

    if flags.count {
        println!("{}", count);
    }

    return count > 0;
}
<commit_msg>Implement filename header switches and defaults in grep<commit_after>extern crate extra;

use std::env;
use std::fs::File;
use std::io;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::process::exit;

static MAN_PAGE: &str = /* @MANSTART{grep} */ r#"
NAME
    grep - print lines matching a pattern

SYNOPSIS
    grep [--help] [-chHnv] PATTERN [FILE...]

DESCRIPTION
    grep searches the named input FILEs for lines containing a match to the given PATTERN. If no
    files are specified, grep searches the standard input. grep prints the matching lines.

OPTIONS
    -c
    --count
        Print count of matching lines, instead of those lines.

    -H
    --with-filename
        Include filename header with each match (default for multiple files).

    -h
    --no-filename
        Never include filename header (default for single files or stdin).

    --help
        Print this manual page.

    -n
    --line-number
        Prefix each line of output with the line number of the match.

    -v
    --invert-match
        Invert matching.
"#; /* @MANEND */

#[derive(Copy, Clone)]
struct Flags {
    line_numbers: bool,
    invert_match: bool,
    count: bool,
    filename_headers: Option<bool>,
}

impl Flags {
    fn new() -> Flags {
        Flags {
            line_numbers: false,
            invert_match: false,
            count: false,
            filename_headers: None,
        }
    }
}

fn main() {
    let args = env::args().skip(1);
    let stdin = io::stdin();
    let stdin = stdin.lock();

    let mut flags = Flags::new();
    let mut pattern = String::new();
    let mut files = Vec::with_capacity(args.len());
    for arg in args {
        if arg.starts_with('-') {
            match arg.as_str() {
                "--help" => {
                    print!("{}", MAN_PAGE);
                    exit(0);
                }
                "-h" | "--no-filename" => flags.filename_headers = Some(false),
                "-H" | "--with-filename" => flags.filename_headers = Some(true),
                "-n" | "--line-number" => flags.line_numbers = true,
                "-v" | "--invert-match" => flags.invert_match = true,
                "-c" | "--count" => flags.count = true,
                _ => {
                    eprintln!("Error, unknown option: {}", arg);
                    exit(2);
                }
            }
        } else if pattern.is_empty() {
            pattern = arg.clone();
        } else {
            files.push(arg)
        }
    }

    if pattern.is_empty() {
        eprintln!("You must provide a pattern");
        exit(2);
    }
    if flags.filename_headers == None {
        flags.filename_headers = Some(files.len() > 1);
    }

    let mut found = false;
    let mut error = false;
    if files.is_empty() {
        found = do_simple_search(BufReader::new(stdin), "(standard input)", &pattern, flags);
    } else {
        for path in files {
            match File::open(&Path::new(&path)) {
                Ok(f) => {
                    found |= do_simple_search(BufReader::new(f), &path, &pattern, flags);
                }
                Err(err) => {
                    eprintln!("Error opening {}: {}", path, err);
                    error = true;
                }
            }
        }
    }
    if error {
        exit(2);
    }
    if !found {
        exit(1);
    }
}

fn do_simple_search<T: BufRead>(reader: T, path: &str, pattern: &str, flags: Flags) -> bool {
    let mut count = 0;
    for (line_num, result) in reader.lines().enumerate() {
        if let Ok(line) = result {
            let mut is_match = line.contains(pattern);
            if flags.invert_match {
                is_match = !is_match
            }
            if is_match {
                count += 1;
                if !flags.count {
                    if flags.filename_headers.unwrap() {
                        print!("{}:", path);
                    }
                    if flags.line_numbers {
                        print!("{}:", line_num + 1);
                    }
                    println!("{}", line);
                }
            }
        }
    }

    if flags.count {
        if flags.filename_headers.unwrap() {
            print!("{}:", path);
        }
        println!("{}", count);
    }

    return count > 0;
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate gate;
extern crate rustyline;

use std::io;
use std::io::Read;

fn main() {
    let matches = clap::App::new("gate")
        .version("0.1.0")
        .author("James Hall")
        .about("A simple programming language.")
        .arg(clap::Arg::with_name("interactive")
            .short("i")
            .long("interactive"))
        .get_matches();

    if matches.is_present("interactive") {
        run_interactive();
    } else {
        run_stdin();
    }
}

fn run_interactive() {
    let mut program = gate::Program::new();
    let mut rl = rustyline::Editor::new();

    'outer: loop {
        let mut line = match rl.readline("> ") {
            Ok(l) => l,
            Err(_) => break 'outer,
        };

        loop {
            let mut needs_more_input = false;
            let mut exprs = vec![];

            {
                let parser = gate::Parser::new(&line);
                for expr_res in parser {
                    match expr_res {
                        Ok(e) => exprs.push(e),
                        Err(gate::ParseError::UnexpectedEOF) => {
                            needs_more_input = true;
                            break;
                        },
                        Err(e) => {
                            println!("{:?}", e);
                            continue 'outer;
                        },
                    }
                }
            }

            if !needs_more_input {
                rl.add_history_entry(&line);

                let mut last_result = gate::Data::Nil;
                for expr in exprs {
                    last_result = expr.eval(&mut program);
                }
                println!("{:?}", last_result);
                continue 'outer;
            } else {
                match rl.readline(">> ") {
                    Ok(l) => line.push_str(&l),
                    Err(_) => break 'outer,
                }
            }
        }
    }
}

fn run_stdin() {
    let mut input = String::new();
    io::stdin().read_to_string(&mut input).unwrap();

    let parser = gate::Parser::new(&input);
    let mut program = gate::Program::new();

    for expr in parser {
        expr.unwrap().eval(&mut program);
    }
}
<commit_msg>Add input file to main<commit_after>extern crate clap;
extern crate gate;
extern crate rustyline;

use std::{fs, io};
use std::io::Read;

fn main() {
    let matches = clap::App::new("gate")
        .version("0.1.0")
        .author("James Hall")
        .about("A simple programming language.")
        .arg(clap::Arg::with_name("interactive")
            .short("i")
            .long("interactive"))
        .arg(clap::Arg::with_name("INPUT")
            .help("An optional file to run"))
        .get_matches();

    let mut program = gate::Program::new();
    let mut has_run = false;

    if let Some(input) = matches.value_of("INPUT") {
        run_file(&mut program, input);
        has_run = true;
    }

    if matches.is_present("interactive") {
        run_interactive(&mut program);
        has_run = true;
    }

    if !has_run {
        run_stdin(&mut program);
    }
}

fn run_interactive(program: &mut gate::Program) {
    let mut rl = rustyline::Editor::new();

    'outer: loop {
        let mut line = match rl.readline("> ") {
            Ok(l) => l,
            Err(_) => break 'outer,
        };

        loop {
            let mut needs_more_input = false;
            let mut exprs = vec![];

            {
                let parser = gate::Parser::new(&line);
                for expr_res in parser {
                    match expr_res {
                        Ok(e) => exprs.push(e),
                        Err(gate::ParseError::UnexpectedEOF) => {
                            needs_more_input = true;
                            break;
                        },
                        Err(e) => {
                            println!("{:?}", e);
                            continue 'outer;
                        },
                    }
                }
            }

            if !needs_more_input {
                rl.add_history_entry(&line);

                let mut last_result = gate::Data::Nil;
                for expr in exprs {
                    last_result = expr.eval(program);
                }
                println!("{:?}", last_result);
                continue 'outer;
            } else {
                match rl.readline(">> ") {
                    Ok(l) => line.push_str(&l),
                    Err(_) => break 'outer,
                }
            }
        }
    }
}

fn run(program: &mut gate::Program, input: String) {
    let parser = gate::Parser::new(&input);
    for expr in parser {
        expr.unwrap().eval(program);
    }
}

fn run_file(program: &mut gate::Program, filename: &str) {
    let mut input_file = fs::File::open(filename).expect("can't open file");
    let mut input = String::new();
    input_file.read_to_string(&mut input).unwrap();
    run(program, input);
}

fn run_stdin(program: &mut gate::Program) {
    let mut input = String::new();
    io::stdin().read_to_string(&mut input).unwrap();
    run(program, input);
}
<|endoftext|>


<commit_before>// this is just a test binary that can be hooked up to Instruments
extern crate lonlat_bng;
use lonlat_bng::{convert_to_bng_threaded, convert_to_osgb36_threaded, Array};

extern crate rand;
use rand::distributions::{IndependentSample, Range};

extern crate libc;

fn main() {
    let num_coords = 10000000;
    let between_lon = Range::new(-6.379880, 1.768960);
    let between_lat = Range::new(49.871159, 55.811741);
    let mut rng = rand::thread_rng();
    let lon_vec = vec![between_lon.ind_sample(&mut rng) as f32; num_coords];
    let lat_vec = vec![between_lat.ind_sample(&mut rng) as f32; num_coords];
    let lon_arr = Array {
        data: lon_vec.as_ptr() as *const libc::c_void,
        len: lon_vec.len() as libc::size_t,
    };
    let lat_arr = Array {
        data: lat_vec.as_ptr() as *const libc::c_void,
        len: lat_vec.len() as libc::size_t,
    };

    convert_to_bng_threaded(lon_arr, lat_arr);
    // convert_to_osgb36_threaded(lon_arr, lat_arr);
}
<commit_msg>Remove unused import<commit_after>// this is just a test binary that can be hooked up to Instruments
extern crate lonlat_bng;
use lonlat_bng::{convert_to_bng_threaded, Array};

extern crate rand;
use rand::distributions::{IndependentSample, Range};

extern crate libc;

fn main() {
    let num_coords = 10000000;
    let between_lon = Range::new(-6.379880, 1.768960);
    let between_lat = Range::new(49.871159, 55.811741);
    let mut rng = rand::thread_rng();
    let lon_vec = vec![between_lon.ind_sample(&mut rng) as f32; num_coords];
    let lat_vec = vec![between_lat.ind_sample(&mut rng) as f32; num_coords];
    let lon_arr = Array {
        data: lon_vec.as_ptr() as *const libc::c_void,
        len: lon_vec.len() as libc::size_t,
    };
    let lat_arr = Array {
        data: lat_vec.as_ptr() as *const libc::c_void,
        len: lat_vec.len() as libc::size_t,
    };

    convert_to_bng_threaded(lon_arr, lat_arr);
    // convert_to_osgb36_threaded(lon_arr, lat_arr);
}
<|endoftext|>


<commit_before>pub mod maintenance;
pub mod registry;

use std::collections::HashSet;

use kite_rocksdb::RocksDBIndexStore;

use analysis::registry::AnalyzerRegistry;
use mapping::{Mapping, FieldMapping, MappingRegistry};

#[derive(Debug)]
pub struct Index {
    name: String,
    pub analyzers: AnalyzerRegistry,
    pub mappings: MappingRegistry,
    pub store: RocksDBIndexStore,
}

impl Index {
    pub fn new(name: String, store: RocksDBIndexStore) -> Index {
        Index {
            name: name,
            analyzers: AnalyzerRegistry::new(),
            mappings: MappingRegistry::new(),
            store: store,
        }
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn get_mapping_by_name(&self, name: &str) -> Option<&Mapping> {
        self.mappings.get(name)
    }

    pub fn get_field_mapping_by_name(&self, name: &str) -> Option<&FieldMapping> {
        self.mappings.get_field(name)
    }
}
<commit_msg>Removed unused import<commit_after>pub mod maintenance;
pub mod registry;

use kite_rocksdb::RocksDBIndexStore;

use analysis::registry::AnalyzerRegistry;
use mapping::{Mapping, FieldMapping, MappingRegistry};

#[derive(Debug)]
pub struct Index {
    name: String,
    pub analyzers: AnalyzerRegistry,
    pub mappings: MappingRegistry,
    pub store: RocksDBIndexStore,
}

impl Index {
    pub fn new(name: String, store: RocksDBIndexStore) -> Index {
        Index {
            name: name,
            analyzers: AnalyzerRegistry::new(),
            mappings: MappingRegistry::new(),
            store: store,
        }
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn get_mapping_by_name(&self, name: &str) -> Option<&Mapping> {
        self.mappings.get(name)
    }

    pub fn get_field_mapping_by_name(&self, name: &str) -> Option<&FieldMapping> {
        self.mappings.get_field(name)
    }
}
<|endoftext|>


<commit_before>//! Print sizes of structs and enums
//!
//! Run with `cargo test sizes -- --nocapture`
//! to get the printed output.

use stencila_schema::*;

macro_rules! sizeof {
    ($type:ident) => {
        {
            let size = std::mem::size_of::<$type>();
            println!("{}: {}", stringify!($type), size);
            size
        }
    };
}

#[test]
fn sizes() {
    sizeof!(Primitive);

    sizeof!(ArrayValidator);
    sizeof!(Article);
    sizeof!(AudioObject);
    sizeof!(BooleanValidator);
    sizeof!(Brand);
    sizeof!(CitationIntentEnumeration);
    sizeof!(Cite);
    sizeof!(CiteGroup);
    sizeof!(Claim);
    sizeof!(Code);
    sizeof!(CodeBlock);
    sizeof!(CodeChunk);
    sizeof!(CodeError);
    sizeof!(CodeExpression);
    sizeof!(CodeFragment);
    sizeof!(Collection);
    sizeof!(Comment);
    sizeof!(ConstantValidator);
    sizeof!(ContactPoint);
    sizeof!(CreativeWork);
    sizeof!(Datatable);
    sizeof!(DatatableColumn);
    sizeof!(Date);
    sizeof!(DefinedTerm);
    sizeof!(Delete);
    sizeof!(Emphasis);
    sizeof!(EnumValidator);
    sizeof!(Enumeration);
    sizeof!(Figure);
    sizeof!(Function);
    sizeof!(Grant);
    sizeof!(Heading);
    sizeof!(ImageObject);
    sizeof!(Include);
    sizeof!(IntegerValidator);
    sizeof!(Link);
    sizeof!(List);
    sizeof!(ListItem);
    sizeof!(Mark);
    sizeof!(Math);
    sizeof!(MathBlock);
    sizeof!(MathFragment);
    sizeof!(MediaObject);
    sizeof!(MonetaryGrant);
    sizeof!(NontextualAnnotation);
    sizeof!(Note);
    sizeof!(NumberValidator);
    sizeof!(Organization);
    sizeof!(Paragraph);
    sizeof!(Parameter);
    sizeof!(Periodical);
    sizeof!(Person);
    sizeof!(PostalAddress);
    sizeof!(Product);
    sizeof!(PropertyValue);
    sizeof!(PublicationIssue);
    sizeof!(PublicationVolume);
    sizeof!(Quote);
    sizeof!(QuoteBlock);
    sizeof!(Review);
    sizeof!(SoftwareApplication);
    sizeof!(SoftwareEnvironment);
    sizeof!(SoftwareSession);
    sizeof!(SoftwareSourceCode);
    sizeof!(StringValidator);
    sizeof!(Strong);
    sizeof!(Subscript);
    sizeof!(Superscript);
    sizeof!(Table);
    sizeof!(TableCell);
    sizeof!(TableRow);
    sizeof!(ThematicBreak);
    sizeof!(Thing);
    sizeof!(TupleValidator);
    sizeof!(Validator);
    sizeof!(Variable);
    sizeof!(VideoObject);
    sizeof!(VolumeMount);

    sizeof!(InlineContent);
    sizeof!(BlockContent);

    sizeof!(CreativeWork);
    sizeof!(CreativeWorkTypes);
}
<commit_msg>test(Rust): Break down by main groupings<commit_after>//! Print sizes of structs and enums
//!
//! Run with `cargo test sizes -- --nocapture`
//! to get the printed output.

use std::collections::BTreeMap;

use stencila_schema::*;

macro_rules! sizeof {
    ($type:ty) => {{
        let size = std::mem::size_of::<$type>();
        println!("{}: {}", stringify!($type), size);
        size
    }};
}

#[test]
fn sizes() {
    println!("");
    println!("----------------------------------------------");
    sizeof!(Node);
    println!("----------------------------------------------");
    sizeof!(ArrayValidator);
    sizeof!(Article);
    sizeof!(AudioObject);
    sizeof!(BooleanValidator);
    sizeof!(Brand);
    sizeof!(CitationIntentEnumeration);
    sizeof!(Cite);
    sizeof!(CiteGroup);
    sizeof!(Claim);
    sizeof!(Code);
    sizeof!(CodeBlock);
    sizeof!(CodeChunk);
    sizeof!(CodeError);
    sizeof!(CodeExpression);
    sizeof!(CodeFragment);
    sizeof!(Collection);
    sizeof!(Comment);
    sizeof!(ConstantValidator);
    sizeof!(ContactPoint);
    sizeof!(CreativeWork);
    sizeof!(Datatable);
    sizeof!(DatatableColumn);
    sizeof!(Date);
    sizeof!(DefinedTerm);
    sizeof!(Delete);
    sizeof!(Emphasis);
    sizeof!(EnumValidator);
    sizeof!(Enumeration);
    sizeof!(Figure);
    sizeof!(Function);
    sizeof!(Grant);
    sizeof!(Heading);
    sizeof!(ImageObject);
    sizeof!(Include);
    sizeof!(IntegerValidator);
    sizeof!(Link);
    sizeof!(List);
    sizeof!(ListItem);
    sizeof!(Mark);
    sizeof!(Math);
    sizeof!(MathBlock);
    sizeof!(MathFragment);
    sizeof!(MediaObject);
    sizeof!(MonetaryGrant);
    sizeof!(NontextualAnnotation);
    sizeof!(Note);
    sizeof!(NumberValidator);
    sizeof!(Organization);
    sizeof!(Paragraph);
    sizeof!(Parameter);
    sizeof!(Periodical);
    sizeof!(Person);
    sizeof!(PostalAddress);
    sizeof!(Product);
    sizeof!(PropertyValue);
    sizeof!(PublicationIssue);
    sizeof!(PublicationVolume);
    sizeof!(Quote);
    sizeof!(QuoteBlock);
    sizeof!(Review);
    sizeof!(SoftwareApplication);
    sizeof!(SoftwareEnvironment);
    sizeof!(SoftwareSession);
    sizeof!(SoftwareSourceCode);
    sizeof!(StringValidator);
    sizeof!(Strong);
    sizeof!(Subscript);
    sizeof!(Superscript);
    sizeof!(Table);
    sizeof!(TableCell);
    sizeof!(TableRow);
    sizeof!(ThematicBreak);
    sizeof!(Thing);
    sizeof!(TupleValidator);
    sizeof!(Validator);
    sizeof!(Variable);
    sizeof!(VideoObject);
    sizeof!(VolumeMount);
    println!("----------------------------------------------");

    println!("");
    println!("----------------------------------------------");
    sizeof!(InlineContent);
    println!("----------------------------------------------");
    sizeof!(AudioObject);
    sizeof!(Cite);
    sizeof!(CiteGroup);
    sizeof!(CodeExpression);
    sizeof!(CodeFragment);
    sizeof!(Delete);
    sizeof!(Emphasis);
    sizeof!(ImageObject);
    sizeof!(Link);
    sizeof!(MathFragment);
    sizeof!(NontextualAnnotation);
    sizeof!(Note);
    sizeof!(Quote);
    sizeof!(Strong);
    sizeof!(Subscript);
    sizeof!(Superscript);
    sizeof!(VideoObject);
    sizeof!(bool);
    sizeof!(i64);
    sizeof!(f64);
    sizeof!(Vec<Primitive>);
    sizeof!(BTreeMap<String, Primitive>);
    sizeof!(String);
    println!("----------------------------------------------");

    println!("");
    println!("----------------------------------------------");
    sizeof!(BlockContent);
    println!("----------------------------------------------");
    sizeof!(Claim);
    sizeof!(CodeBlock);
    sizeof!(CodeChunk);
    sizeof!(Collection);
    sizeof!(Figure);
    sizeof!(Heading);
    sizeof!(List);
    sizeof!(MathBlock);
    sizeof!(Paragraph);
    sizeof!(QuoteBlock);
    sizeof!(Table);
    sizeof!(ThematicBreak);
    println!("----------------------------------------------");

    println!("");
    println!("----------------------------------------------");
    sizeof!(CreativeWorkTypes);
    println!("----------------------------------------------");
    sizeof!(CreativeWork);
    sizeof!(Article);
    sizeof!(AudioObject);
    sizeof!(Claim);
    sizeof!(Collection);
    sizeof!(Comment);
    sizeof!(Datatable);
    sizeof!(Figure);
    sizeof!(ImageObject);
    sizeof!(MediaObject);
    sizeof!(Periodical);
    sizeof!(PublicationIssue);
    sizeof!(PublicationVolume);
    sizeof!(Review);
    sizeof!(SoftwareApplication);
    sizeof!(SoftwareSourceCode);
    sizeof!(Table);
    sizeof!(VideoObject);
    println!("----------------------------------------------");
}
<|endoftext|>