<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: Vec<HashMap<Identifier, Value>>,
}

impl Environment {
    fn new() -> Environment {
        Environment { values: vec![HashMap::new()] }
    }

    fn push(&mut self) {
        self.values.push(HashMap::new());
    }

    fn pop(&mut self) {
        self.values.pop();
    }

    fn top(&self) -> usize {
        self.values.len() - 1
    }

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

    fn try_set(&mut self, identifier: Identifier, value: Value) -> bool {
        for index in (0..self.values.len()).rev() {
            if self.values[index].contains_key(&identifier) {
                self.values[index].insert(identifier, value);
                return true;
            }
        }
        false
    }

    fn get(&self, identifier: &Identifier) -> Option<&Value> {
        for index in (0..self.values.len()).rev() {
            if let Some(value) = self.values[index].get(identifier) {
                return Some(value);
            }
        }
        None
    }
}

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) => {
                if environment.try_set(target.clone(), value.clone()) {
                    Ok(value.clone())
                } else {
                    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
                         })
            }
            Statement::Block(ref b) => {
                environment.push();
                let mut result = Ok(None);
                for statement in &b.statements {
                    result = statement.execute(environment);
                }
                environment.pop();
                result
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use ast::*;
    use interpreter::{Interpret, Execute, 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());
    }

    #[test]
    fn expression_statement() {
        let mut environment = Environment::new();
        let expr = Expr::Literal(Literal::NumberLiteral(1.0f64));
        let statement = Statement::Expression(expr);
        assert_eq!(Some(Value::Number(1.0f64)),
                   statement.execute(&mut environment).unwrap());
    }

    #[test]
    fn complex_expression_statement() {
        let mut environment = Environment::new();
        let subexpr1 = UnaryExpr {
            operator: UnaryOperator::Minus,
            right: Expr::Literal(Literal::NumberLiteral(2f64)),
        };
        let subexpr2 = Grouping { expr: Expr::Literal(Literal::NumberLiteral(5f64)) };
        let binary_expr = BinaryExpr {
            left: Expr::Unary(Box::new(subexpr1)),
            operator: BinaryOperator::Star,
            right: Expr::Grouping(Box::new(subexpr2)),
        };
        let expr = Expr::Binary(Box::new(binary_expr));
        let statement = Statement::Expression(expr);
        assert_eq!(Some(Value::Number(-10.0f64)),
                   statement.execute(&mut environment).unwrap());
    }

    #[test]
    fn variable_definition() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let statement = Statement::VariableDefinition(identifier.clone());
        assert_eq!(None, statement.execute(&mut environment).unwrap());
        assert_eq!(&Value::Nil, environment.get(&identifier).unwrap());
    }

    #[test]
    fn error_accessing_undefined_variable() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let statement = Statement::Expression(Expr::Identifier(identifier));
        assert!(statement.execute(&mut environment).is_err());
    }

    #[test]
    fn error_assigning_undefined_variable() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let statement = Statement::Expression(
            Expr::Assignment(Box::new(Assignment{
                lvalue: Target::Identifier(identifier),
                rvalue: Expr::Literal(Literal::BoolLiteral(true))}))
            );
        assert!(statement.execute(&mut environment).is_err());
    }

    #[test]
    fn variable_definition_with_initializer() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let expr = Expr::Literal(Literal::NumberLiteral(1.0f64));
        let statement = Statement::VariableDefinitionWithInitalizer(identifier.clone(), expr);
        assert_eq!(None, statement.execute(&mut environment).unwrap());
        assert_eq!(&Value::Number(1.0f64),
                   environment.get(&identifier).unwrap());
    }

    #[test]
    fn block_affects_outer_scope() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let expr = Expr::Literal(Literal::NumberLiteral(1.0f64));
        let outer_statement = Statement::VariableDefinitionWithInitalizer(identifier.clone(), expr);
        assert_eq!(None, outer_statement.execute(&mut environment).unwrap());

        let statements = vec![
            Statement::Expression(
                Expr::Assignment(Box::new(Assignment{
                    lvalue: Target::Identifier(Identifier{name: "x".into()}),
                    rvalue: Expr::Literal(Literal::BoolLiteral(false))})))];
        let block = Statement::Block(Box::new(Block { statements: statements }));
        assert!(block.execute(&mut environment).is_ok());
        assert_eq!(&Value::Boolean(false),
                   environment.get(&identifier).unwrap());
    }
    #[test]
    fn block_variable_dont_escape_scope() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let expr = Expr::Literal(Literal::NumberLiteral(1.0f64));
        let statements = vec![Statement::VariableDefinitionWithInitalizer(identifier.clone(),
                                                                          expr)];
        let block = Statement::Block(Box::new(Block { statements: statements }));
        assert_eq!(None, block.execute(&mut environment).unwrap());
        // The variable declaration gets lost when we exit the scope
        assert_eq!(None, environment.get(&identifier));
    }

    #[test]
    fn truth_table() {
        // Note that lox follows Ruby's rules, not Javascript's
        assert_eq!(false, Value::Nil.is_true());
        assert_eq!(true, Value::Boolean(true).is_true());
        assert_eq!(false, Value::Boolean(false).is_true());
        assert_eq!(true, Value::Number(1.0f64).is_true());
        assert_eq!(true, Value::Number(0.0f64).is_true());
        assert_eq!(true, Value::String("".into()).is_true());
        assert_eq!(true, Value::String("Hello World!".into()).is_true());
    }

}
<commit_msg>Test for stringify<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 {
    values: Vec<HashMap<Identifier, Value>>,
}

impl Environment {
    fn new() -> Environment {
        Environment { values: vec![HashMap::new()] }
    }

    fn push(&mut self) {
        self.values.push(HashMap::new());
    }

    fn pop(&mut self) {
        self.values.pop();
    }

    fn top(&self) -> usize {
        self.values.len() - 1
    }

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

    fn try_set(&mut self, identifier: Identifier, value: Value) -> bool {
        for index in (0..self.values.len()).rev() {
            if self.values[index].contains_key(&identifier) {
                self.values[index].insert(identifier, value);
                return true;
            }
        }
        false
    }

    fn get(&self, identifier: &Identifier) -> Option<&Value> {
        for index in (0..self.values.len()).rev() {
            if let Some(value) = self.values[index].get(identifier) {
                return Some(value);
            }
        }
        None
    }
}

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) => {
                if environment.try_set(target.clone(), value.clone()) {
                    Ok(value.clone())
                } else {
                    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
                         })
            }
            Statement::Block(ref b) => {
                environment.push();
                let mut result = Ok(None);
                for statement in &b.statements {
                    result = statement.execute(environment);
                }
                environment.pop();
                result
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use ast::*;
    use interpreter::{Interpret, Execute, 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());
    }

    #[test]
    fn expression_statement() {
        let mut environment = Environment::new();
        let expr = Expr::Literal(Literal::NumberLiteral(1.0f64));
        let statement = Statement::Expression(expr);
        assert_eq!(Some(Value::Number(1.0f64)),
                   statement.execute(&mut environment).unwrap());
    }

    #[test]
    fn complex_expression_statement() {
        let mut environment = Environment::new();
        let subexpr1 = UnaryExpr {
            operator: UnaryOperator::Minus,
            right: Expr::Literal(Literal::NumberLiteral(2f64)),
        };
        let subexpr2 = Grouping { expr: Expr::Literal(Literal::NumberLiteral(5f64)) };
        let binary_expr = BinaryExpr {
            left: Expr::Unary(Box::new(subexpr1)),
            operator: BinaryOperator::Star,
            right: Expr::Grouping(Box::new(subexpr2)),
        };
        let expr = Expr::Binary(Box::new(binary_expr));
        let statement = Statement::Expression(expr);
        assert_eq!(Some(Value::Number(-10.0f64)),
                   statement.execute(&mut environment).unwrap());
    }

    #[test]
    fn variable_definition() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let statement = Statement::VariableDefinition(identifier.clone());
        assert_eq!(None, statement.execute(&mut environment).unwrap());
        assert_eq!(&Value::Nil, environment.get(&identifier).unwrap());
    }

    #[test]
    fn error_accessing_undefined_variable() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let statement = Statement::Expression(Expr::Identifier(identifier));
        assert!(statement.execute(&mut environment).is_err());
    }

    #[test]
    fn error_assigning_undefined_variable() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let statement = Statement::Expression(
            Expr::Assignment(Box::new(Assignment{
                lvalue: Target::Identifier(identifier),
                rvalue: Expr::Literal(Literal::BoolLiteral(true))}))
            );
        assert!(statement.execute(&mut environment).is_err());
    }

    #[test]
    fn variable_definition_with_initializer() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let expr = Expr::Literal(Literal::NumberLiteral(1.0f64));
        let statement = Statement::VariableDefinitionWithInitalizer(identifier.clone(), expr);
        assert_eq!(None, statement.execute(&mut environment).unwrap());
        assert_eq!(&Value::Number(1.0f64),
                   environment.get(&identifier).unwrap());
    }

    #[test]
    fn block_affects_outer_scope() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let expr = Expr::Literal(Literal::NumberLiteral(1.0f64));
        let outer_statement = Statement::VariableDefinitionWithInitalizer(identifier.clone(), expr);
        assert_eq!(None, outer_statement.execute(&mut environment).unwrap());

        let statements = vec![
            Statement::Expression(
                Expr::Assignment(Box::new(Assignment{
                    lvalue: Target::Identifier(Identifier{name: "x".into()}),
                    rvalue: Expr::Literal(Literal::BoolLiteral(false))})))];
        let block = Statement::Block(Box::new(Block { statements: statements }));
        assert!(block.execute(&mut environment).is_ok());
        assert_eq!(&Value::Boolean(false),
                   environment.get(&identifier).unwrap());
    }
    #[test]
    fn block_variable_dont_escape_scope() {
        let mut environment = Environment::new();
        let identifier = Identifier { name: "x".into() };
        let expr = Expr::Literal(Literal::NumberLiteral(1.0f64));
        let statements = vec![Statement::VariableDefinitionWithInitalizer(identifier.clone(),
                                                                          expr)];
        let block = Statement::Block(Box::new(Block { statements: statements }));
        assert_eq!(None, block.execute(&mut environment).unwrap());
        // The variable declaration gets lost when we exit the scope
        assert_eq!(None, environment.get(&identifier));
    }

    #[test]
    fn truth_table() {
        // Note that lox follows Ruby's rules, not Javascript's
        assert_eq!(false, Value::Nil.is_true());
        assert_eq!(true, Value::Boolean(true).is_true());
        assert_eq!(false, Value::Boolean(false).is_true());
        assert_eq!(true, Value::Number(1.0f64).is_true());
        assert_eq!(true, Value::Number(0.0f64).is_true());
        assert_eq!(true, Value::String("".into()).is_true());
        assert_eq!(true, Value::String("Hello World!".into()).is_true());
    }

    #[test]
    fn to_string() {
        // Note that lox follows Ruby's rules, not Javascript's
        assert_eq!("nil", Value::Nil.to_string());
        assert_eq!("true", Value::Boolean(true).to_string());
        assert_eq!("false", Value::Boolean(false).to_string());
        assert_eq!("1", Value::Number(1.0f64).to_string());
        assert_eq!("0", Value::Number(0.0f64).to_string());
        assert_eq!("", Value::String("".into()).to_string());
        assert_eq!("Hello World!",
                   Value::String("Hello World!".into()).to_string());
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;

use rust_decimal::Decimal;

use ast::*;
use ir::{Number, ConversionRatio};
use unit_graph::UnitGraph;
use symbols::SymbolTable;
use canonical::{self, CanonicalUnit};

#[derive(Debug, Clone)]
pub enum DeclError<'a> {
    UndeclaredName {
        name: Ident<'a>,
        span: Span<'a>,
    },
    UndeclaredUnit {
        name: UnitName<'a>,
        span: Span<'a>,
    },
    DuplicateUnitDecl {
        name: UnitName<'a>,
        span: Span<'a>,
    },
    UnknownAttribute {
        name: Ident<'a>,
        span: Span<'a>,
    },
    DuplicateConst {
        name: Ident<'a>,
        span: Span<'a>,
    },
    UnsupportedConstExpr {
        expr: Expr<'a>,
        span: Span<'a>,
    },
    MismatchedUnit {
        expected: UnitExpr<'a>,
        found: UnitExpr<'a>,
        span: Span<'a>,
    },
    ConversionFailed(ConversionFailed, Span<'a>),
}

impl<'a> From<canonical::UndeclaredUnit<'a>> for DeclError<'a> {
    fn from(canonical::UndeclaredUnit {name, span}: canonical::UndeclaredUnit<'a>) -> Self {
        DeclError::UndeclaredUnit {name, span}
    }
}

#[derive(Debug, Clone)]
pub enum EvalError<'a> {
    UndeclaredName {
        name: Ident<'a>,
        span: Span<'a>,
    },
    UndeclaredUnit {
        name: UnitName<'a>,
        span: Span<'a>,
    },
    MismatchedUnit {
        expected: UnitExpr<'a>,
        found: UnitExpr<'a>,
        span: Span<'a>,
    },
    ConversionFailed(ConversionFailed, Span<'a>),
}

impl<'a> From<canonical::UndeclaredUnit<'a>> for EvalError<'a> {
    fn from(canonical::UndeclaredUnit {name, span}: canonical::UndeclaredUnit<'a>) -> Self {
        EvalError::UndeclaredUnit {name, span}
    }
}

#[derive(Debug, Clone)]
pub struct ConversionFailed {
    start: CanonicalUnit,
    end: CanonicalUnit,
}

#[derive(Debug, Clone, Default)]
pub struct Interpreter<'a> {
    units: UnitGraph<'a>,
    symbols: SymbolTable<'a>,
}

impl<'a> Interpreter<'a> {
    pub fn print_unit(&self, unit: &CanonicalUnit) {
        let mut names = unit.iter_unit_names(&self.units);

        let print_unit = |(unit_name, exp)| {
            if exp != 1 {
                print!("{}^{}", unit_name, exp);
            }
            else {
                print!("{}", unit_name);
            }
        };
        if let Some(pair) = names.next() {
            print_unit(pair);
        }
        for pair in names {
            print!(" ");
            print_unit(pair);
        }
    }

    /// Load declarations into the global scope of the interpreter
    pub fn load_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        // We need to do this in several passes in order to satisfy the potential items each type
        // of declaration might need.

        // Macros need to be expanded before anything else
        let program = self.expand_macros(Cow::Borrowed(program))?;

        self.load_unit_decls(&program)?;
        // Constants need units so we can verify their declared unit if provided.
        self.load_const_decls(&program)?;
        // Conversions need both units and constants (+ const functions) so we can evaluate their
        // declared ratios
        self.load_conversion_decls(&program)?;

        // Functions will need the units loaded so we can verify that their parameter and return
        // units are declared. We also check the body of each function at this point to make sure
        // all unit conversions are mathematically valid so we need those loaded as well.
        self.load_fn_decls(&program)?;

        Ok(())
    }

    /// Expand any macros used in the program
    ///
    /// Any declared macros will be collected along the way and used as necessary while
    /// recursively expanding the macros
    fn expand_macros<'c>(&self, program: Cow<'c, Program<'a>>) -> Result<Cow<'c, Program<'a>>, DeclError<'a>> {
        // By using Cow here, we avoid an unnecessary clone if the program has no macros

        for decl in &program.decls {
            //TODO: Macro declarations will be processed here eventually

            if let Decl::MacroInvoke(_) = decl {
                unimplemented!();
            }
        }
        Ok(program)
    }

    /// Load declared units into the global unit graph of the interpreter
    fn load_unit_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            if let &Decl::UnitDecl(UnitDecl {ref attrs, unit_name, span, ..}) = decl {
                //TODO: insert the unit into the unit graph and add the single conversion from
                //unitless to the unit

                for &Attribute {name, tokens: _, span} in attrs {
                    match name {
                        "prefix" => {}, //TODO
                        _ => return Err(DeclError::UnknownAttribute {name, span}),
                    }
                }

                self.units.insert_unit(unit_name, span)
                    .map_err(|_| DeclError::DuplicateUnitDecl {name: unit_name, span})?;
            }
        }
        Ok(())
    }

    /// Load declared constants and `const fn`s into the global scope of the interpreter
    fn load_const_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            //TODO: const fn declarations will be processed and unit checked here eventually

            if let &Decl::Constant(Constant {name, unit: ref unit_expr, ref value, span}) = decl {
                let unit = CanonicalUnit::from_unit_expr(unit_expr, &self.units)?;
                let value = match value {
                    &Expr::Number(NumericLiteral {ref value, span: const_span}, ref const_unit) => {
                        // Units must match
                        if CanonicalUnit::from_unit_expr(const_unit, &self.units)? == unit {
                            *value
                        }
                        else {
                            return Err(DeclError::MismatchedUnit {
                                expected: unit_expr.clone(),
                                found: const_unit.clone(),
                                span: const_span,
                            })
                        }
                    },
                    _ => return Err(DeclError::UnsupportedConstExpr {expr: value.clone(), span}),
                };
                self.symbols.insert_const(name, value, unit, span).map_err(|_| {
                    DeclError::DuplicateConst {name, span}
                })?;
            }
        }
        Ok(())
    }

    /// Load unit conversions and evaluate any const exprs found within them
    fn load_conversion_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            match decl {
                // Aliases need to be processed later when all the units have already been walked
                Decl::UnitDecl(UnitDecl {unit_name, alias_for: Some(alias), ..}) => {
                    let unit_id = self.units.unit_id(*unit_name)
                        .expect("bug: unit should have already been declared");
                    let left_unit = CanonicalUnit::from(unit_id);
                    let right_unit = CanonicalUnit::from_unit_expr(alias, &self.units)?;

                    // Alias means: 1 left_unit == 1 right_unit
                    self.units.add_conversion(ConversionRatio {
                        left: Number {
                            value: Decimal::from(1),
                            unit: left_unit,
                        },
                        right: Number {
                            value: Decimal::from(1),
                            unit: right_unit,
                        },
                    })
                },
                Decl::ConversionDecl(ConversionDecl {left, right, ..}) => {
                    let left = self.reduce_const_expr(left)?;
                    let right = self.reduce_const_expr(right)?;
                    self.units.add_conversion(ConversionRatio {left, right});
                },
                _ => {},
            }
        }
        Ok(())
    }

    /// Load function declarations into the global scope and check their bodies to ensure that any
    /// conversions are valid
    fn load_fn_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            if let Decl::Function(_) = decl {
                unimplemented!();
            }
        }
        Ok(())
    }

    fn reduce_const_expr(&self, expr: &Expr<'a>) -> Result<Number, DeclError<'a>> {
        match expr {
            &Expr::Number(NumericLiteral {value, span: _}, ref unit) => {
                let unit = CanonicalUnit::from_unit_expr(unit, &self.units)?;
                Ok(Number {value, unit})
            },
            &Expr::Ident(ref path, span) => {
                if path.len() != 1 { unimplemented!() }
                let name = path.first().unwrap();
                self.symbols.get_const(name).cloned().ok_or_else(|| DeclError::UndeclaredName {name, span})
            },
            Expr::ConvertTo(expr, target_unit, span) => {
                let number = self.reduce_const_expr(expr)?;
                let target_unit = CanonicalUnit::from_unit_expr(target_unit, &self.units)?;
                if number.unit.is_unitless() {
                    Ok(Number {
                        value: number.value,
                        unit: target_unit,
                    })
                }
                else {
                    self.convert(number, target_unit)
                        .map_err(|err| DeclError::ConversionFailed(err, *span))
                }
            },
            Expr::Add(_, _, span) | Expr::Sub(_, _, span) | Expr::Mul(_, _, span) |
            Expr::Div(_, _, span) | Expr::Mod(_, _, span) | Expr::Pow(_, _, span) |
            Expr::Call(_, _, span) | Expr::MacroCall(MacroInvoke {span, ..}) |
            Expr::Return(_, span) | Expr::UnitValue(span) => {
                Err(DeclError::UnsupportedConstExpr {expr: expr.clone(), span: *span})
            },
            Expr::Block(_) => unimplemented!(),
        }
    }

    pub fn evaluate_expr(&self, expr: &Expr<'a>) -> Result<Number, EvalError<'a>> {
        Ok(match expr {
            &Expr::Number(NumericLiteral {value, span: _}, ref unit) => {
                let unit = CanonicalUnit::from_unit_expr(unit, &self.units)?;
                Number {value, unit}
            },
            &Expr::Ident(ref path, span) => {
                if path.len() != 1 { unimplemented!() }
                let name = path.first().unwrap();
                //TODO: Allow getting variables defined with `let` in the interpreter
                self.symbols.get_const(name).cloned().ok_or_else(|| EvalError::UndeclaredName {name, span})?
            },
            Expr::ConvertTo(expr, target_unit, span) => {
                let number = self.evaluate_expr(expr)?;
                let target_unit = CanonicalUnit::from_unit_expr(target_unit, &self.units)?;
                if number.unit.is_unitless() {
                    Number {
                        value: number.value,
                        unit: target_unit,
                    }
                }
                else {
                    self.convert(number, target_unit)
                        .map_err(|err| EvalError::ConversionFailed(err, *span))?
                }
            },
            Expr::Add(lhs, rhs, span) => {
                let lhs = self.evaluate_expr(lhs)?;
                let rhs = self.convert(self.evaluate_expr(rhs)?, lhs.unit.clone())
                    .map_err(|err| EvalError::ConversionFailed(err, *span))?;
                Number {
                    value: lhs.value + rhs.value,
                    unit: lhs.unit,
                }
            },
            Expr::Sub(lhs, rhs, span) => {
                let lhs = self.evaluate_expr(lhs)?;
                let rhs = self.convert(self.evaluate_expr(rhs)?, lhs.unit.clone())
                    .map_err(|err| EvalError::ConversionFailed(err, *span))?;
                Number {
                    value: lhs.value - rhs.value,
                    unit: lhs.unit,
                }
            },
            Expr::Mul(lhs, rhs, _) => {
                let lhs = self.evaluate_expr(lhs)?;
                let rhs = self.evaluate_expr(rhs)?;
                Number {
                    value: lhs.value * rhs.value,
                    unit: lhs.unit * rhs.unit,
                }
            },
            Expr::Div(lhs, rhs, _) => {
                let lhs = self.evaluate_expr(lhs)?;
                let rhs = self.evaluate_expr(rhs)?;
                Number {
                    value: lhs.value / rhs.value,
                    unit: lhs.unit / rhs.unit,
                }
            },
            _ => unimplemented!(),
        })
    }

    /// Attempts to convert the given value to the given unit
    ///
    /// Does not automatically promote unitless to the target unit as that is not valid in all cases
    fn convert(&self, number: Number, target_unit: CanonicalUnit) -> Result<Number, ConversionFailed> {
        if number.unit == target_unit {
            // No conversion necessary
            Ok(number)
        }
        else {
            let path = self.units.conversion_path(&number.unit, &target_unit)
                .ok_or_else(|| ConversionFailed {start: number.unit.clone(), end: target_unit.clone()})?;
            let factor = path.conversion_factor();
            Ok(Number {
                value: number.value * factor,
                unit: target_unit,
            })
        }
    }
}
<commit_msg>Attempt to convert during multiplication and division and give up if it doesn't work<commit_after>use std::borrow::Cow;

use rust_decimal::Decimal;

use ast::*;
use ir::{Number, ConversionRatio};
use unit_graph::UnitGraph;
use symbols::SymbolTable;
use canonical::{self, CanonicalUnit};

#[derive(Debug, Clone)]
pub enum DeclError<'a> {
    UndeclaredName {
        name: Ident<'a>,
        span: Span<'a>,
    },
    UndeclaredUnit {
        name: UnitName<'a>,
        span: Span<'a>,
    },
    DuplicateUnitDecl {
        name: UnitName<'a>,
        span: Span<'a>,
    },
    UnknownAttribute {
        name: Ident<'a>,
        span: Span<'a>,
    },
    DuplicateConst {
        name: Ident<'a>,
        span: Span<'a>,
    },
    UnsupportedConstExpr {
        expr: Expr<'a>,
        span: Span<'a>,
    },
    MismatchedUnit {
        expected: UnitExpr<'a>,
        found: UnitExpr<'a>,
        span: Span<'a>,
    },
    ConversionFailed(ConversionFailed, Span<'a>),
}

impl<'a> From<canonical::UndeclaredUnit<'a>> for DeclError<'a> {
    fn from(canonical::UndeclaredUnit {name, span}: canonical::UndeclaredUnit<'a>) -> Self {
        DeclError::UndeclaredUnit {name, span}
    }
}

#[derive(Debug, Clone)]
pub enum EvalError<'a> {
    UndeclaredName {
        name: Ident<'a>,
        span: Span<'a>,
    },
    UndeclaredUnit {
        name: UnitName<'a>,
        span: Span<'a>,
    },
    MismatchedUnit {
        expected: UnitExpr<'a>,
        found: UnitExpr<'a>,
        span: Span<'a>,
    },
    ConversionFailed(ConversionFailed, Span<'a>),
}

impl<'a> From<canonical::UndeclaredUnit<'a>> for EvalError<'a> {
    fn from(canonical::UndeclaredUnit {name, span}: canonical::UndeclaredUnit<'a>) -> Self {
        EvalError::UndeclaredUnit {name, span}
    }
}

#[derive(Debug, Clone)]
pub struct ConversionFailed {
    start: CanonicalUnit,
    end: CanonicalUnit,
}

#[derive(Debug, Clone, Default)]
pub struct Interpreter<'a> {
    units: UnitGraph<'a>,
    symbols: SymbolTable<'a>,
}

impl<'a> Interpreter<'a> {
    pub fn print_unit(&self, unit: &CanonicalUnit) {
        let mut names = unit.iter_unit_names(&self.units);

        let print_unit = |(unit_name, exp)| {
            if exp != 1 {
                print!("{}^{}", unit_name, exp);
            }
            else {
                print!("{}", unit_name);
            }
        };
        if let Some(pair) = names.next() {
            print_unit(pair);
        }
        for pair in names {
            print!(" ");
            print_unit(pair);
        }
    }

    /// Load declarations into the global scope of the interpreter
    pub fn load_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        // We need to do this in several passes in order to satisfy the potential items each type
        // of declaration might need.

        // Macros need to be expanded before anything else
        let program = self.expand_macros(Cow::Borrowed(program))?;

        self.load_unit_decls(&program)?;
        // Constants need units so we can verify their declared unit if provided.
        self.load_const_decls(&program)?;
        // Conversions need both units and constants (+ const functions) so we can evaluate their
        // declared ratios
        self.load_conversion_decls(&program)?;

        // Functions will need the units loaded so we can verify that their parameter and return
        // units are declared. We also check the body of each function at this point to make sure
        // all unit conversions are mathematically valid so we need those loaded as well.
        self.load_fn_decls(&program)?;

        Ok(())
    }

    /// Expand any macros used in the program
    ///
    /// Any declared macros will be collected along the way and used as necessary while
    /// recursively expanding the macros
    fn expand_macros<'c>(&self, program: Cow<'c, Program<'a>>) -> Result<Cow<'c, Program<'a>>, DeclError<'a>> {
        // By using Cow here, we avoid an unnecessary clone if the program has no macros

        for decl in &program.decls {
            //TODO: Macro declarations will be processed here eventually

            if let Decl::MacroInvoke(_) = decl {
                unimplemented!();
            }
        }
        Ok(program)
    }

    /// Load declared units into the global unit graph of the interpreter
    fn load_unit_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            if let &Decl::UnitDecl(UnitDecl {ref attrs, unit_name, span, ..}) = decl {
                //TODO: insert the unit into the unit graph and add the single conversion from
                //unitless to the unit

                for &Attribute {name, tokens: _, span} in attrs {
                    match name {
                        "prefix" => {}, //TODO
                        _ => return Err(DeclError::UnknownAttribute {name, span}),
                    }
                }

                self.units.insert_unit(unit_name, span)
                    .map_err(|_| DeclError::DuplicateUnitDecl {name: unit_name, span})?;
            }
        }
        Ok(())
    }

    /// Load declared constants and `const fn`s into the global scope of the interpreter
    fn load_const_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            //TODO: const fn declarations will be processed and unit checked here eventually

            if let &Decl::Constant(Constant {name, unit: ref unit_expr, ref value, span}) = decl {
                let unit = CanonicalUnit::from_unit_expr(unit_expr, &self.units)?;
                let value = match value {
                    &Expr::Number(NumericLiteral {ref value, span: const_span}, ref const_unit) => {
                        // Units must match
                        if CanonicalUnit::from_unit_expr(const_unit, &self.units)? == unit {
                            *value
                        }
                        else {
                            return Err(DeclError::MismatchedUnit {
                                expected: unit_expr.clone(),
                                found: const_unit.clone(),
                                span: const_span,
                            })
                        }
                    },
                    _ => return Err(DeclError::UnsupportedConstExpr {expr: value.clone(), span}),
                };
                self.symbols.insert_const(name, value, unit, span).map_err(|_| {
                    DeclError::DuplicateConst {name, span}
                })?;
            }
        }
        Ok(())
    }

    /// Load unit conversions and evaluate any const exprs found within them
    fn load_conversion_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            match decl {
                // Aliases need to be processed later when all the units have already been walked
                Decl::UnitDecl(UnitDecl {unit_name, alias_for: Some(alias), ..}) => {
                    let unit_id = self.units.unit_id(*unit_name)
                        .expect("bug: unit should have already been declared");
                    let left_unit = CanonicalUnit::from(unit_id);
                    let right_unit = CanonicalUnit::from_unit_expr(alias, &self.units)?;

                    // Alias means: 1 left_unit == 1 right_unit
                    self.units.add_conversion(ConversionRatio {
                        left: Number {
                            value: Decimal::from(1),
                            unit: left_unit,
                        },
                        right: Number {
                            value: Decimal::from(1),
                            unit: right_unit,
                        },
                    })
                },
                Decl::ConversionDecl(ConversionDecl {left, right, ..}) => {
                    let left = self.reduce_const_expr(left)?;
                    let right = self.reduce_const_expr(right)?;
                    self.units.add_conversion(ConversionRatio {left, right});
                },
                _ => {},
            }
        }
        Ok(())
    }

    /// Load function declarations into the global scope and check their bodies to ensure that any
    /// conversions are valid
    fn load_fn_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            if let Decl::Function(_) = decl {
                unimplemented!();
            }
        }
        Ok(())
    }

    fn reduce_const_expr(&self, expr: &Expr<'a>) -> Result<Number, DeclError<'a>> {
        match expr {
            &Expr::Number(NumericLiteral {value, span: _}, ref unit) => {
                let unit = CanonicalUnit::from_unit_expr(unit, &self.units)?;
                Ok(Number {value, unit})
            },
            &Expr::Ident(ref path, span) => {
                if path.len() != 1 { unimplemented!() }
                let name = path.first().unwrap();
                self.symbols.get_const(name).cloned().ok_or_else(|| DeclError::UndeclaredName {name, span})
            },
            Expr::ConvertTo(expr, target_unit, span) => {
                let number = self.reduce_const_expr(expr)?;
                let target_unit = CanonicalUnit::from_unit_expr(target_unit, &self.units)?;
                if number.unit.is_unitless() {
                    Ok(Number {
                        value: number.value,
                        unit: target_unit,
                    })
                }
                else {
                    self.convert(number, target_unit)
                        .map_err(|err| DeclError::ConversionFailed(err, *span))
                }
            },
            Expr::Add(_, _, span) | Expr::Sub(_, _, span) | Expr::Mul(_, _, span) |
            Expr::Div(_, _, span) | Expr::Mod(_, _, span) | Expr::Pow(_, _, span) |
            Expr::Call(_, _, span) | Expr::MacroCall(MacroInvoke {span, ..}) |
            Expr::Return(_, span) | Expr::UnitValue(span) => {
                Err(DeclError::UnsupportedConstExpr {expr: expr.clone(), span: *span})
            },
            Expr::Block(_) => unimplemented!(),
        }
    }

    pub fn evaluate_expr(&self, expr: &Expr<'a>) -> Result<Number, EvalError<'a>> {
        Ok(match expr {
            &Expr::Number(NumericLiteral {value, span: _}, ref unit) => {
                let unit = CanonicalUnit::from_unit_expr(unit, &self.units)?;
                Number {value, unit}
            },
            &Expr::Ident(ref path, span) => {
                if path.len() != 1 { unimplemented!() }
                let name = path.first().unwrap();
                //TODO: Allow getting variables defined with `let` in the interpreter
                self.symbols.get_const(name).cloned().ok_or_else(|| EvalError::UndeclaredName {name, span})?
            },
            Expr::ConvertTo(expr, target_unit, span) => {
                let number = self.evaluate_expr(expr)?;
                let target_unit = CanonicalUnit::from_unit_expr(target_unit, &self.units)?;
                if number.unit.is_unitless() {
                    Number {
                        value: number.value,
                        unit: target_unit,
                    }
                }
                else {
                    self.convert(number, target_unit)
                        .map_err(|err| EvalError::ConversionFailed(err, *span))?
                }
            },
            Expr::Add(lhs, rhs, span) => {
                let lhs = self.evaluate_expr(lhs)?;
                let rhs = self.convert(self.evaluate_expr(rhs)?, lhs.unit.clone())
                    .map_err(|err| EvalError::ConversionFailed(err, *span))?;
                Number {
                    value: lhs.value + rhs.value,
                    unit: lhs.unit,
                }
            },
            Expr::Sub(lhs, rhs, span) => {
                let lhs = self.evaluate_expr(lhs)?;
                let rhs = self.convert(self.evaluate_expr(rhs)?, lhs.unit.clone())
                    .map_err(|err| EvalError::ConversionFailed(err, *span))?;
                Number {
                    value: lhs.value - rhs.value,
                    unit: lhs.unit,
                }
            },
            Expr::Mul(lhs, rhs, _) => {
                let lhs = self.evaluate_expr(lhs)?;
                let rhs = self.evaluate_expr(rhs)?;
                // Attempt to convert if possible, but otherwise just leave it
                let rhs = self.convert(rhs.clone(), lhs.unit.clone()).unwrap_or_else(|_| rhs);
                Number {
                    value: lhs.value * rhs.value,
                    unit: lhs.unit * rhs.unit,
                }
            },
            Expr::Div(lhs, rhs, _) => {
                let lhs = self.evaluate_expr(lhs)?;
                let rhs = self.evaluate_expr(rhs)?;
                // Attempt to convert if possible, but otherwise just leave it
                let rhs = self.convert(rhs.clone(), lhs.unit.clone()).unwrap_or_else(|_| rhs);
                Number {
                    value: lhs.value / rhs.value,
                    unit: lhs.unit / rhs.unit,
                }
            },
            _ => unimplemented!(),
        })
    }

    /// Attempts to convert the given value to the given unit
    ///
    /// Does not automatically promote unitless to the target unit as that is not valid in all cases
    fn convert(&self, number: Number, target_unit: CanonicalUnit) -> Result<Number, ConversionFailed> {
        if number.unit == target_unit {
            // No conversion necessary
            Ok(number)
        }
        else {
            let path = self.units.conversion_path(&number.unit, &target_unit)
                .ok_or_else(|| ConversionFailed {start: number.unit.clone(), end: target_unit.clone()})?;
            let factor = path.conversion_factor();
            Ok(Number {
                value: number.value * factor,
                unit: target_unit,
            })
        }
    }
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Ben Gamari <bgamari@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
## I/O register interface

On most embedded platforms interaction with hardware peripherals
occurs through memory-mapped registers. This crate provides a syntax
extension for `rustc` to generate convenient, type-safe register
interfaces from a minimal definition.

### Concepts

A *register* is group of bits (typically a word, although on some
platforms smaller). By manipulating the bits of a register one can
affect the state of the associated peripheral.

### Example register definition

Let's consider a register block for a simple UART-like peripheral. The
documentation for the peripheral will likely have a table defining the
interface resembling the following,

```notrust
offset       name         description
───────      ────────     ──────────────────────────
0x0          CR           Configuration register
  bit 0      RXE          Receive enable
  bit 1      TXE          Transmit enable
  bit 2      RXIE         Recieve interrupt enable
  bit 3      TXIE         Transmit interrupt enable
  bit 12:4   BR           Baudrate
  bit 16:14  PARITY       Parity
                            0x0     No parity
                            0x1     Reserved
                            0x2     Even parity
                            0x3     Odd parity

0x4          SR           Status register
  bit 0      RXNE         Receive data register not empty flag (read-only)
  bit 1      TXE          Transmit data register not empty flag (read-only)
  bit 2      FE           Framing error flag (set to clear)

0x8          DR           Data register
  bits 7:0   D            Read returns received data
                          Write transmits data
```

The syntax extension is invoked through through the `ioregs!` macro. A
register definition for the above peripheral might look like this,

```
ioregs!(UART = {
    0x0    => reg32 cr {
        0      => rxe,
        1      => txe,
        2      => rxie,
        3      => txie,
        4..12  => br,
        14..16 => parity {
          0x0  => NoParity,
          0x2  => EvenParity,
          0x3  => OddParity,
        }
    }

    0x4    => reg32 sr {
        0      => rxne: ro,
        1      => txe: ro,
        2      => fe: set_to_clear,
    }

    0x8    => reg32 dr {
        0..7   => d
    }
})
```

Here we've defined a register block called `UART` consisting of a
three registers: `cr`, `sr`, and `dr`. Each register definition
consists of an offset from the beginning of the register block width,
a register type giving the width of the register (`reg32` in this
case), a name, and a list of fields.

The `cr` register has four boolean flags, an integer
field `br`, and a field `parity` with four possible values
(`NoParity`, `EvenParity`, and `OddParity`). Each field is defined by
a bit or bit range, a name, some optional modifiers (e.g. `ro` in the
case of `rxne`), and an optional list of values.

This register definition will produce a variety of types, along with
associated accessor methods for convenient, safe manipulation of the
described registers. In the process of generating these, `ioregs!`
will perform a variety of sanity checks (e.g. ensuring that registers
and bitfields are free of overlap).

#### Documenting register definitions

It is highly recommended that register definitions include
docstrings. Registers, fields, and `enum` values can all be annotated
with docstrings with the typical Rust doc comment syntax. Both outer
(`/// comment`) and inner (`//! comment`) comments are accepted. Inner
comments apply to the item to which the current block belongs whereas
outer comments apply to the item that follows. In addition,
trailing comments are supported with the `//=` syntax. These apply
to the preceding item, allowing definitions and associated comments
to inhabit the same line. Multiple successive comments of the same
type will be concatenated together into a single doc comment.

For instance, we might document the above example as follows,

```
ioregs!(UART = {
    /// Control register
    /// Here is some discussion of the function of the `cr` register.
    0x0    => reg32 cr {
        0      => rxe,         //= Receive enable
        1      => txe,         //= Transmit enable
        2      => rxie,        //= Receive interrupt enable
        3      => txie,        //= Transmit interrupt enable
        4..12  => br,          //= Baud rate
        14..16 => parity {     //! Parity selection
          0x0  => NoParity,    //= No parity
          0x2  => EvenParity,  //= Even parity
          0x3  => OddParity,   //= Odd parity
        }
    }

    ...
})
```

#### Nesting register blocks

In addition to primitive register types (e.g. `reg32`), one can also
nest groups of logically related registers. For instance, in the case
of a DMA peripheral it is common that the same block of registers will
be replicated, one for each DMA channel. This can be accomplished with
`ioregs!` as follows,

```
ioregs!(DMA = {
    0x0    => reg32 cr { ... }
    0x10   => group channel[4] {
        0x0    => reg32 cr { ... }
        0x4    => reg32 sr { ... }
    }
    0x30   => reg32 sr { ... }
})
```

This will produce the following layout in memory,

```notrust
address        register
────────       ──────────────
0x0            cr
0x10           channel[0].cr
0x14           channel[0].sr
0x18           channel[1].cr
0x1c           channel[1].sr
0x20           channel[2].cr
0x24           channel[2].sr
0x28           channel[3].cr
0x2c           channel[3].sr
0x30           sr
```

### What is produced

The `ioregs!` extension produces a variety of types and methods for
each register and field. Let's start by examining the top-level types
representing the structure of the interface.

```
pub enum UART_cr_parity {
    NoParity = 0, EvenParity = 2, OddParity = 3,
}

pub struct UART_cr { ... }
pub struct UART_sr { ... }
pub struct UART_dr { ... }

pub struct UART {
    pub cr: UART_cr,
    pub sr: UART_sr,
    pub dr: UART_dr,
}
```

The `UART` struct is the the "entry-point" into the interface and is
ultimately what will be instantiated to represent the peripheral's
register window, typically as a `static extern` item,

```
extern { pub static UART: UART; }
```

The register structs (`UART_cr`, `UART_sr`, and `UART_dr`)
have no user visible members but expose a variety of methods. Let's
look at `cr` in particular,

```
impl UART_cr {
    pub fn get(&self) -> UART_cr_Get { ... }

    pub fn set_rxe(&self, new_value: bool) -> UART_cr_Update { ... }
    pub fn rxe(&self) -> bool { ... }

    // similar methods for `txe`, `rxie`, `txie`

    pub fn set_br(&self, new_value: u32) -> UART_cr_Update { ... }
    pub fn br(&self) -> u32 { ... }

    pub fn set_parity(&self, new_value: UART_cr_parity) -> UART_cr_Update { ... }
    pub fn parity(&self) -> UART_cr_parity { ... }
}
```

Here we see each field has a corresponding "get" function (e.g. `rxe`,
`br`, and `parity`) as well as a "set" function. Note that the set
function returns a `UART_cr_Update` object. This object mirrors the
setter methods of `UART_cr`, collecting multiple field updates within
a register, performing them on destruction with the `Drop` trait,

```
pub struct UART_cr_Update { ... }
impl Drop for UART_cr_Update { ... }

impl UART_cr_Update {
    pub fn set_rxe<'a>(&'a mut self, new_value: bool) -> &'a mut UART_cr_Update { ... }
    pub fn set_txe<'a>(&'a mut self, new_value: bool) -> &'a mut UART_cr_Update { ... }
    ...
}
```

As the set methods return references to `self` they can be easily
chained together. For instance, we can update the `rxe` and `txe`
fields of the `cr` register atomically,

```
UART.cr.set_rxe(true).set_txe(false);
```

In addition to get and set methods, `UART_cr` also implements a `get`
method which returns a `UART_cr_Get` object mirroring the get methods
of `UART_cr`. This object captures the state of the register allowing
field values to be later atomically queried,

```
let cr: UART_cr_Get = UART.cr.get();
format!("txe={}, rxe={}, br={}", cr.txe(), cr.rxe(), cr.br())
```

In the case of read-only (resp. write-only) fields the set (resp. get)
method is omitted. In the case of `set_to_clear` fields a `clear`
method is instead produced in place of `set`. For instance, in the
case of the `sr` register's `fe` flag,

```
pub fn fe(self: &UART_sr_Getter) -> bool { ... }
pub fn clear_fe(self: &UART_sr_Update) -> UART_sr_Update { ... }
```

### Informal grammar

In the below discussion `THING, ...` will denote a list of one or more
`THING`s. The `THING`s must be comma separated except when ending
with a brace-enclosed block. Optional elements are enclosed in `⟦...⟧`
brackets.

The `ioregs!` macro expects a definition of the form,

```
ioregs!(IDENT = { REG, ... })
```

Where a `REG` is either a register group,

```notrust
OFFSET => group IDENT⟦[COUNT]⟧ { REG, ... }
```

or a primitive register,

```notrust
OFFSET => TYPE IDENT⟦[COUNT]⟧ { FIELD, ... }
```

`COUNT` is an integer count and a register `TYPE` is one of `reg8` (a
one byte wide register), `reg16` (two bytes wide), or `reg32` (four
bytes wide).

A field is given by

```notrust
BITS => IDENT⟦[COUNT]⟧ ⟦: MODIFIER⟧ ⟦{ VALUE, ... }⟧
```

where `BITS` is either an inclusive range of integers (`N..M`) or a
single integer (shorthand for `N..N`). If a list of values is given
the field is of an enumerated type. Otherwise single bit fields are
of type `bool` and wider fields unsigned integers (in particular, of
the same width as the containing register).

A `MODIFIER` is one of `rw` (read/write), `ro` (read-only), `wo`
(write-only), or `set_to_clear` (a flag which can be cleared by
setting to one).

A `VALUE` is given by,

```notrust
N => NAME
```

*/

#![feature(quote, plugin_registrar, associated_types)]
#![crate_name="ioreg"]
#![crate_type="dylib"]

extern crate rustc;
extern crate syntax;
extern crate serialize;

use rustc::plugin::Registry;
use syntax::ast;
use syntax::ptr::P;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult};
use syntax::util::small_vector::SmallVector;

pub mod node;
pub mod parser;
pub mod builder;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
  reg.register_macro("ioregs", macro_ioregs);
}

pub fn macro_ioregs(cx: &mut ExtCtxt, _: Span, tts: &[ast::TokenTree])
                    -> Box<MacResult+'static> {
  match parser::Parser::new(cx, tts).parse_ioregs() {
    Some(group) => {
      let mut builder = builder::Builder::new();
      let items = builder.emit_items(cx, group);
      MacItems::new(items)
    },
    None => {
      panic!();
    }
  }
}

pub struct MacItems {
  items: Vec<P<ast::Item>>
}

impl MacItems {
  pub fn new(items: Vec<P<ast::Item>>) -> Box<MacResult+'static> {
    Box::new(MacItems { items: items })
  }
}

impl MacResult for MacItems {
  fn make_items(self: Box<MacItems>) -> Option<SmallVector<P<ast::Item>>> {
    Some(SmallVector::many(self.items.clone()))
  }
}
<commit_msg>ioreg: feature(associated_types) now unnecessary<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Ben Gamari <bgamari@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
## I/O register interface

On most embedded platforms interaction with hardware peripherals
occurs through memory-mapped registers. This crate provides a syntax
extension for `rustc` to generate convenient, type-safe register
interfaces from a minimal definition.

### Concepts

A *register* is group of bits (typically a word, although on some
platforms smaller). By manipulating the bits of a register one can
affect the state of the associated peripheral.

### Example register definition

Let's consider a register block for a simple UART-like peripheral. The
documentation for the peripheral will likely have a table defining the
interface resembling the following,

```notrust
offset       name         description
───────      ────────     ──────────────────────────
0x0          CR           Configuration register
  bit 0      RXE          Receive enable
  bit 1      TXE          Transmit enable
  bit 2      RXIE         Recieve interrupt enable
  bit 3      TXIE         Transmit interrupt enable
  bit 12:4   BR           Baudrate
  bit 16:14  PARITY       Parity
                            0x0     No parity
                            0x1     Reserved
                            0x2     Even parity
                            0x3     Odd parity

0x4          SR           Status register
  bit 0      RXNE         Receive data register not empty flag (read-only)
  bit 1      TXE          Transmit data register not empty flag (read-only)
  bit 2      FE           Framing error flag (set to clear)

0x8          DR           Data register
  bits 7:0   D            Read returns received data
                          Write transmits data
```

The syntax extension is invoked through through the `ioregs!` macro. A
register definition for the above peripheral might look like this,

```
ioregs!(UART = {
    0x0    => reg32 cr {
        0      => rxe,
        1      => txe,
        2      => rxie,
        3      => txie,
        4..12  => br,
        14..16 => parity {
          0x0  => NoParity,
          0x2  => EvenParity,
          0x3  => OddParity,
        }
    }

    0x4    => reg32 sr {
        0      => rxne: ro,
        1      => txe: ro,
        2      => fe: set_to_clear,
    }

    0x8    => reg32 dr {
        0..7   => d
    }
})
```

Here we've defined a register block called `UART` consisting of a
three registers: `cr`, `sr`, and `dr`. Each register definition
consists of an offset from the beginning of the register block width,
a register type giving the width of the register (`reg32` in this
case), a name, and a list of fields.

The `cr` register has four boolean flags, an integer
field `br`, and a field `parity` with four possible values
(`NoParity`, `EvenParity`, and `OddParity`). Each field is defined by
a bit or bit range, a name, some optional modifiers (e.g. `ro` in the
case of `rxne`), and an optional list of values.

This register definition will produce a variety of types, along with
associated accessor methods for convenient, safe manipulation of the
described registers. In the process of generating these, `ioregs!`
will perform a variety of sanity checks (e.g. ensuring that registers
and bitfields are free of overlap).

#### Documenting register definitions

It is highly recommended that register definitions include
docstrings. Registers, fields, and `enum` values can all be annotated
with docstrings with the typical Rust doc comment syntax. Both outer
(`/// comment`) and inner (`//! comment`) comments are accepted. Inner
comments apply to the item to which the current block belongs whereas
outer comments apply to the item that follows. In addition,
trailing comments are supported with the `//=` syntax. These apply
to the preceding item, allowing definitions and associated comments
to inhabit the same line. Multiple successive comments of the same
type will be concatenated together into a single doc comment.

For instance, we might document the above example as follows,

```
ioregs!(UART = {
    /// Control register
    /// Here is some discussion of the function of the `cr` register.
    0x0    => reg32 cr {
        0      => rxe,         //= Receive enable
        1      => txe,         //= Transmit enable
        2      => rxie,        //= Receive interrupt enable
        3      => txie,        //= Transmit interrupt enable
        4..12  => br,          //= Baud rate
        14..16 => parity {     //! Parity selection
          0x0  => NoParity,    //= No parity
          0x2  => EvenParity,  //= Even parity
          0x3  => OddParity,   //= Odd parity
        }
    }

    ...
})
```

#### Nesting register blocks

In addition to primitive register types (e.g. `reg32`), one can also
nest groups of logically related registers. For instance, in the case
of a DMA peripheral it is common that the same block of registers will
be replicated, one for each DMA channel. This can be accomplished with
`ioregs!` as follows,

```
ioregs!(DMA = {
    0x0    => reg32 cr { ... }
    0x10   => group channel[4] {
        0x0    => reg32 cr { ... }
        0x4    => reg32 sr { ... }
    }
    0x30   => reg32 sr { ... }
})
```

This will produce the following layout in memory,

```notrust
address        register
────────       ──────────────
0x0            cr
0x10           channel[0].cr
0x14           channel[0].sr
0x18           channel[1].cr
0x1c           channel[1].sr
0x20           channel[2].cr
0x24           channel[2].sr
0x28           channel[3].cr
0x2c           channel[3].sr
0x30           sr
```

### What is produced

The `ioregs!` extension produces a variety of types and methods for
each register and field. Let's start by examining the top-level types
representing the structure of the interface.

```
pub enum UART_cr_parity {
    NoParity = 0, EvenParity = 2, OddParity = 3,
}

pub struct UART_cr { ... }
pub struct UART_sr { ... }
pub struct UART_dr { ... }

pub struct UART {
    pub cr: UART_cr,
    pub sr: UART_sr,
    pub dr: UART_dr,
}
```

The `UART` struct is the the "entry-point" into the interface and is
ultimately what will be instantiated to represent the peripheral's
register window, typically as a `static extern` item,

```
extern { pub static UART: UART; }
```

The register structs (`UART_cr`, `UART_sr`, and `UART_dr`)
have no user visible members but expose a variety of methods. Let's
look at `cr` in particular,

```
impl UART_cr {
    pub fn get(&self) -> UART_cr_Get { ... }

    pub fn set_rxe(&self, new_value: bool) -> UART_cr_Update { ... }
    pub fn rxe(&self) -> bool { ... }

    // similar methods for `txe`, `rxie`, `txie`

    pub fn set_br(&self, new_value: u32) -> UART_cr_Update { ... }
    pub fn br(&self) -> u32 { ... }

    pub fn set_parity(&self, new_value: UART_cr_parity) -> UART_cr_Update { ... }
    pub fn parity(&self) -> UART_cr_parity { ... }
}
```

Here we see each field has a corresponding "get" function (e.g. `rxe`,
`br`, and `parity`) as well as a "set" function. Note that the set
function returns a `UART_cr_Update` object. This object mirrors the
setter methods of `UART_cr`, collecting multiple field updates within
a register, performing them on destruction with the `Drop` trait,

```
pub struct UART_cr_Update { ... }
impl Drop for UART_cr_Update { ... }

impl UART_cr_Update {
    pub fn set_rxe<'a>(&'a mut self, new_value: bool) -> &'a mut UART_cr_Update { ... }
    pub fn set_txe<'a>(&'a mut self, new_value: bool) -> &'a mut UART_cr_Update { ... }
    ...
}
```

As the set methods return references to `self` they can be easily
chained together. For instance, we can update the `rxe` and `txe`
fields of the `cr` register atomically,

```
UART.cr.set_rxe(true).set_txe(false);
```

In addition to get and set methods, `UART_cr` also implements a `get`
method which returns a `UART_cr_Get` object mirroring the get methods
of `UART_cr`. This object captures the state of the register allowing
field values to be later atomically queried,

```
let cr: UART_cr_Get = UART.cr.get();
format!("txe={}, rxe={}, br={}", cr.txe(), cr.rxe(), cr.br())
```

In the case of read-only (resp. write-only) fields the set (resp. get)
method is omitted. In the case of `set_to_clear` fields a `clear`
method is instead produced in place of `set`. For instance, in the
case of the `sr` register's `fe` flag,

```
pub fn fe(self: &UART_sr_Getter) -> bool { ... }
pub fn clear_fe(self: &UART_sr_Update) -> UART_sr_Update { ... }
```

### Informal grammar

In the below discussion `THING, ...` will denote a list of one or more
`THING`s. The `THING`s must be comma separated except when ending
with a brace-enclosed block. Optional elements are enclosed in `⟦...⟧`
brackets.

The `ioregs!` macro expects a definition of the form,

```
ioregs!(IDENT = { REG, ... })
```

Where a `REG` is either a register group,

```notrust
OFFSET => group IDENT⟦[COUNT]⟧ { REG, ... }
```

or a primitive register,

```notrust
OFFSET => TYPE IDENT⟦[COUNT]⟧ { FIELD, ... }
```

`COUNT` is an integer count and a register `TYPE` is one of `reg8` (a
one byte wide register), `reg16` (two bytes wide), or `reg32` (four
bytes wide).

A field is given by

```notrust
BITS => IDENT⟦[COUNT]⟧ ⟦: MODIFIER⟧ ⟦{ VALUE, ... }⟧
```

where `BITS` is either an inclusive range of integers (`N..M`) or a
single integer (shorthand for `N..N`). If a list of values is given
the field is of an enumerated type. Otherwise single bit fields are
of type `bool` and wider fields unsigned integers (in particular, of
the same width as the containing register).

A `MODIFIER` is one of `rw` (read/write), `ro` (read-only), `wo`
(write-only), or `set_to_clear` (a flag which can be cleared by
setting to one).

A `VALUE` is given by,

```notrust
N => NAME
```

*/

#![feature(quote, plugin_registrar)]
#![crate_name="ioreg"]
#![crate_type="dylib"]

extern crate rustc;
extern crate syntax;
extern crate serialize;

use rustc::plugin::Registry;
use syntax::ast;
use syntax::ptr::P;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult};
use syntax::util::small_vector::SmallVector;

pub mod node;
pub mod parser;
pub mod builder;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
  reg.register_macro("ioregs", macro_ioregs);
}

pub fn macro_ioregs(cx: &mut ExtCtxt, _: Span, tts: &[ast::TokenTree])
                    -> Box<MacResult+'static> {
  match parser::Parser::new(cx, tts).parse_ioregs() {
    Some(group) => {
      let mut builder = builder::Builder::new();
      let items = builder.emit_items(cx, group);
      MacItems::new(items)
    },
    None => {
      panic!();
    }
  }
}

pub struct MacItems {
  items: Vec<P<ast::Item>>
}

impl MacItems {
  pub fn new(items: Vec<P<ast::Item>>) -> Box<MacResult+'static> {
    Box::new(MacItems { items: items })
  }
}

impl MacResult for MacItems {
  fn make_items(self: Box<MacItems>) -> Option<SmallVector<P<ast::Item>>> {
    Some(SmallVector::many(self.items.clone()))
  }
}
<|endoftext|>