<commit_before>use std::error::Error;
use std::fs::File;
use std::iter::Peekable;
use std::str::Chars;

use super::sql::*;

//pub enum Keyword {
//    Select,
//    From,
//    Where
//}

#[derive(Debug,Clone,PartialEq)]
pub enum Token {
    Identifier(String),
    Keyword(String),
    Operator(String),
    Number(String),
    Comma,
    Whitespace,
    Eq,
    Neq,
    Lt,
    Gt,
    LtEq,
    GtEq,
    Plus,
    Minus,
    Mult,
    Div,
    LParen,
    RParen,

    //Operator(String)
}

#[derive(Debug,Clone)]
pub enum ParserError {
    TokenizerError(String),
    ParserError(String),
}

struct Tokenizer {
    query: String,
}

impl Tokenizer {

    pub fn tokenize(&mut self) -> Result<Vec<Token>, ParserError> {

        let mut peekable = self.query.chars().peekable();

        let mut tokens : Vec<Token> = vec![];

        while let Some(token) = self.next_token(&mut peekable)? {
            tokens.push(token);
        }

        Ok(tokens.into_iter().filter(|t| match t {
            &Token::Whitespace => false,
            _ => true
        }).collect())
    }

    fn next_token(&self, chars: &mut Peekable<Chars>) -> Result<Option<Token>, ParserError> {
        match chars.peek() {
            Some(&ch) => match ch {
                // whitespace
                ' ' | '\t' | '\n' => {
                    chars.next(); // consume
                    Ok(Some(Token::Whitespace))
                },
                // identifier or keyword
                'a' ... 'z' | 'A' ... 'Z' | '_' | '@' => {
                    let mut s = String::new();
                    while let Some(&ch) = chars.peek() {
                        match ch {
                            'a' ... 'z' | 'A' ... 'Z' | '_' | '0' ... '9' => {
                                chars.next(); // consume
                                s.push(ch);
                            },
                            _ => break
                        }
                    }
                    match s.to_uppercase().as_ref() {
                        "SELECT" | "FROM" | "WHERE" | "LIMIT" | "ORDER" | "GROUP" | "BY" |
                        "UNION" | "ALL"| "UPDATE" | "DELETE" | "IN" | "NOT" | "NULL" |
                        "SET" => Ok(Some(Token::Keyword(s))),
                        _ => Ok(Some(Token::Identifier(s))),
                    }
                },
                // numbers
                '0' ... '9' => {
                    let mut s = String::new();
                    while let Some(&ch) = chars.peek() {
                        match ch {
                            '0' ... '9' => {
                                chars.next(); // consume
                                s.push(ch);
                            },
                            _ => break
                        }
                    }
                    Ok(Some(Token::Number(s)))
                },
                // operators
                '+' => { chars.next(); Ok(Some(Token::Plus)) },
                '-' => { chars.next(); Ok(Some(Token::Minus)) },
                '*' => { chars.next(); Ok(Some(Token::Mult)) },
                '/' => { chars.next(); Ok(Some(Token::Div)) },
                '=' => { chars.next(); Ok(Some(Token::Eq)) },
                '<' => {
                    chars.next(); // consume
                    match chars.peek() {
                        Some(&ch) => match ch {
                            '=' => {
                                chars.next();
                                Ok(Some(Token::LtEq))
                            },
                            '>' => {
                                chars.next();
                                Ok(Some(Token::Neq))
                            },
                            _ => Ok(Some(Token::Lt))
                        },
                        None => Ok(Some(Token::Lt))
                    }
                },
                '>' => {
                    chars.next(); // consume
                    match chars.peek() {
                        Some(&ch) => match ch {
                            '=' => {
                                chars.next();
                                Ok(Some(Token::GtEq))
                            },
                            _ => Ok(Some(Token::Gt))
                        },
                        None => Ok(Some(Token::Gt))
                    }
                },
                _ => Err(ParserError::TokenizerError(
                    String::from(format!("unhandled char '{}' in tokenizer", ch))))
            },
            None => Ok(None)
        }
    }
}

pub struct Parser {
    tokens: Vec<Token>,
    index: usize
}

impl Parser {

    pub fn new(tokens: Vec<Token>) -> Self {
        Parser { tokens: tokens, index: 0 }
    }

    pub fn parse(&mut self) -> Result<ASTNode, ParserError> {
        self.parse_expr(0)
    }

    fn parse_expr(&mut self, precedence: u8) -> Result<ASTNode, ParserError> {

        let mut expr = self.parse_prefix()?;

        while let Some(tok) = self.next_token() {

            let next_precedence = self.get_precedence(&tok)?;
            if precedence >= next_precedence {
                break;
            }

            expr = self.parse_infix(expr, next_precedence)?;
        }

        Ok(expr)
    }

    fn parse_prefix(&mut self) -> Result<ASTNode, ParserError> {
        Err(ParserError::TokenizerError(String::from("not implemented yet")))
    }

    fn parse_infix(&mut self, expr: ASTNode, precedence: u8) -> Result<ASTNode, ParserError> {
        Err(ParserError::TokenizerError(String::from("not implemented yet")))
    }

    fn get_precedence(&self, tok: &Token) -> Result<u8, ParserError> {
        match tok {
            &Token::Eq | &Token::Lt | & Token::LtEq |
            &Token::Neq | &Token::Gt | & Token::GtEq => Ok(20),
            &Token::Plus | &Token::Minus => Ok(30),
            &Token::Mult | &Token::Div => Ok(40),
            _ => Err(ParserError::TokenizerError(String::from("invalid token for get_precendence")))
        }
    }

    fn next_token(&mut self) -> Option<Token> {
        if self.index < self.tokens.len() {
            self.index = self.index + 1;
            Some(self.tokens[self.index-1].clone())
        } else {
            None
        }
    }

}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn tokenize_select_1()  {
        let sql = String::from("SELECT 1");
        let mut tokenizer = Tokenizer { query: sql };
        let tokens = tokenizer.tokenize().unwrap();
        println!("tokens = {:?}", tokens);
        assert_eq!(2, tokens.len());
        assert_eq!(Token::Keyword(String::from("SELECT")), tokens[0]);
        assert_eq!(Token::Number(String::from("1")), tokens[1]);
    }

    #[test]
    fn tokenize_simple_select()  {
        let sql = String::from("SELECT * FROM customer WHERE id = 1");
        let mut tokenizer = Tokenizer { query: sql };
        let tokens = tokenizer.tokenize().unwrap();
        println!("tokens = {:?}", tokens);
        assert_eq!(8, tokens.len());
        assert_eq!(Token::Keyword(String::from("SELECT")), tokens[0]);
        assert_eq!(Token::Mult, tokens[1]);
        assert_eq!(Token::Keyword(String::from("FROM")), tokens[2]);
        assert_eq!(Token::Identifier(String::from("customer")), tokens[3]);
        assert_eq!(Token::Keyword(String::from("WHERE")), tokens[4]);
        assert_eq!(Token::Identifier(String::from("id")), tokens[5]);
        assert_eq!(Token::Eq, tokens[6]);
        assert_eq!(Token::Number(String::from("1")), tokens[7]);
    }
}

<commit_msg>save progress on parser<commit_after>use std::error::Error;
use std::fs::File;
use std::iter::Peekable;
use std::str::Chars;

use super::sql::*;

//pub enum Keyword {
//    Select,
//    From,
//    Where
//}

#[derive(Debug,Clone,PartialEq)]
pub enum Token {
    Identifier(String),
    Keyword(String),
    Operator(String),
    Number(String),
    Comma,
    Whitespace,
    Eq,
    Neq,
    Lt,
    Gt,
    LtEq,
    GtEq,
    Plus,
    Minus,
    Mult,
    Div,
    LParen,
    RParen,

    //Operator(String)
}

#[derive(Debug,Clone)]
pub enum ParserError {
    TokenizerError(String),
    ParserError(String),
}

struct Tokenizer {
    query: String,
}

impl Tokenizer {

    pub fn tokenize(&mut self) -> Result<Vec<Token>, ParserError> {

        let mut peekable = self.query.chars().peekable();

        let mut tokens : Vec<Token> = vec![];

        while let Some(token) = self.next_token(&mut peekable)? {
            tokens.push(token);
        }

        Ok(tokens.into_iter().filter(|t| match t {
            &Token::Whitespace => false,
            _ => true
        }).collect())
    }

    fn next_token(&self, chars: &mut Peekable<Chars>) -> Result<Option<Token>, ParserError> {
        match chars.peek() {
            Some(&ch) => match ch {
                // whitespace
                ' ' | '\t' | '\n' => {
                    chars.next(); // consume
                    Ok(Some(Token::Whitespace))
                },
                // identifier or keyword
                'a' ... 'z' | 'A' ... 'Z' | '_' | '@' => {
                    let mut s = String::new();
                    while let Some(&ch) = chars.peek() {
                        match ch {
                            'a' ... 'z' | 'A' ... 'Z' | '_' | '0' ... '9' => {
                                chars.next(); // consume
                                s.push(ch);
                            },
                            _ => break
                        }
                    }
                    match s.to_uppercase().as_ref() {
                        "SELECT" | "FROM" | "WHERE" | "LIMIT" | "ORDER" | "GROUP" | "BY" |
                        "UNION" | "ALL"| "UPDATE" | "DELETE" | "IN" | "NOT" | "NULL" |
                        "SET" => Ok(Some(Token::Keyword(s))),
                        _ => Ok(Some(Token::Identifier(s))),
                    }
                },
                // numbers
                '0' ... '9' => {
                    let mut s = String::new();
                    while let Some(&ch) = chars.peek() {
                        match ch {
                            '0' ... '9' => {
                                chars.next(); // consume
                                s.push(ch);
                            },
                            _ => break
                        }
                    }
                    Ok(Some(Token::Number(s)))
                },
                // operators
                '+' => { chars.next(); Ok(Some(Token::Plus)) },
                '-' => { chars.next(); Ok(Some(Token::Minus)) },
                '*' => { chars.next(); Ok(Some(Token::Mult)) },
                '/' => { chars.next(); Ok(Some(Token::Div)) },
                '=' => { chars.next(); Ok(Some(Token::Eq)) },
                '<' => {
                    chars.next(); // consume
                    match chars.peek() {
                        Some(&ch) => match ch {
                            '=' => {
                                chars.next();
                                Ok(Some(Token::LtEq))
                            },
                            '>' => {
                                chars.next();
                                Ok(Some(Token::Neq))
                            },
                            _ => Ok(Some(Token::Lt))
                        },
                        None => Ok(Some(Token::Lt))
                    }
                },
                '>' => {
                    chars.next(); // consume
                    match chars.peek() {
                        Some(&ch) => match ch {
                            '=' => {
                                chars.next();
                                Ok(Some(Token::GtEq))
                            },
                            _ => Ok(Some(Token::Gt))
                        },
                        None => Ok(Some(Token::Gt))
                    }
                },
                _ => Err(ParserError::TokenizerError(
                    String::from(format!("unhandled char '{}' in tokenizer", ch))))
            },
            None => Ok(None)
        }
    }
}

pub struct Parser {
    tokens: Vec<Token>,
    index: usize
}

impl Parser {

    pub fn new(tokens: Vec<Token>) -> Self {
        Parser { tokens: tokens, index: 0 }
    }

    pub fn parse(&mut self) -> Result<ASTNode, ParserError> {
        self.parse_expr(0)
    }

    fn parse_expr(&mut self, precedence: u8) -> Result<ASTNode, ParserError> {

        let mut expr = self.parse_prefix()?;

        while let Some(tok) = self.next_token() {

            let next_precedence = self.get_precedence(&tok)?;
            if precedence >= next_precedence {
                break;
            }

            expr = self.parse_infix(expr, next_precedence)?;
        }

        Ok(expr)
    }

    fn parse_prefix(&mut self) -> Result<ASTNode, ParserError> {
        match self.next_token() {
            Some(Token::Keyword(k)) => {
                match k.to_uppercase().as_ref() {
                    "SELECT" => Ok(self.parse_select()?),
                    _ => Err(ParserError::TokenizerError(
                        format!("No prefix parser for keyword {}", k))),
                }
            },
            _ => Err(ParserError::TokenizerError(
                format!("Prefix parser expected a keyword")))
        }
    }

    fn parse_infix(&mut self, expr: ASTNode, precedence: u8) -> Result<ASTNode, ParserError> {
        Err(ParserError::ParserError(String::from("parse_infix() not implemented yet")))
    }

    fn get_precedence(&self, tok: &Token) -> Result<u8, ParserError> {
        match tok {
            &Token::Eq | &Token::Lt | & Token::LtEq |
            &Token::Neq | &Token::Gt | & Token::GtEq => Ok(20),
            &Token::Plus | &Token::Minus => Ok(30),
            &Token::Mult | &Token::Div => Ok(40),
            _ => Err(ParserError::TokenizerError(String::from("invalid token for get_precendence")))
        }
    }

    fn peek_token(&mut self) -> Option<Token> {
        if self.index < self.tokens.len() {
            Some(self.tokens[self.index].clone())
        } else {
            None
        }
    }

    fn next_token(&mut self) -> Option<Token> {
        if self.index < self.tokens.len() {
            self.index = self.index + 1;
            Some(self.tokens[self.index-1].clone())
        } else {
            None
        }
    }

    // specific methods

    fn parse_select(&self) -> Result<ASTNode, ParserError> {
        Ok(ASTNode::SQLSelect {
            projection: vec![],
            selection: None,
            relation: None,
            limit: None,
            order: None,
        })
    }

}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn tokenize_select_1()  {
        let sql = String::from("SELECT 1");
        let mut tokenizer = Tokenizer { query: sql };
        let tokens = tokenizer.tokenize().unwrap();
        println!("tokens = {:?}", tokens);
        assert_eq!(2, tokens.len());
        assert_eq!(Token::Keyword(String::from("SELECT")), tokens[0]);
        assert_eq!(Token::Number(String::from("1")), tokens[1]);
    }

    #[test]
    fn tokenize_simple_select()  {
        let sql = String::from("SELECT * FROM customer WHERE id = 1");
        let mut tokenizer = Tokenizer { query: sql };
        let tokens = tokenizer.tokenize().unwrap();
        println!("tokens = {:?}", tokens);
        assert_eq!(8, tokens.len());
        assert_eq!(Token::Keyword(String::from("SELECT")), tokens[0]);
        assert_eq!(Token::Mult, tokens[1]);
        assert_eq!(Token::Keyword(String::from("FROM")), tokens[2]);
        assert_eq!(Token::Identifier(String::from("customer")), tokens[3]);
        assert_eq!(Token::Keyword(String::from("WHERE")), tokens[4]);
        assert_eq!(Token::Identifier(String::from("id")), tokens[5]);
        assert_eq!(Token::Eq, tokens[6]);
        assert_eq!(Token::Number(String::from("1")), tokens[7]);
    }

    #[test]
    fn parse_simple_select() {
        let sql = String::from("SELECT * FROM customer WHERE id = 1");
        let mut tokenizer = Tokenizer { query: sql };
        let tokens = tokenizer.tokenize().unwrap();
        let mut parser = Parser::new(tokens);
        let ast = parser.parse().unwrap();
        println!("AST = {:?}", ast);
    }
}

<|endoftext|>


<commit_before>use Renderable;
use LiquidOptions;
use value::Value;
use variable::Variable;
use text::Text;
use std::slice::Iter;
use output::Output;
use output::FilterPrototype;
use output::VarOrVal;
use lexer::Token;
use lexer::Token::{Identifier, Colon, Comma, Pipe, StringLiteral, NumberLiteral};
use lexer::Element;
use lexer::Element::{Expression, Tag, Raw};
use error::{Error, Result};

pub fn parse<'a>(elements: &[Element],
                 options: &'a LiquidOptions)
                 -> Result<Vec<Box<Renderable + 'a>>> {
    let mut ret = vec![];
    let mut iter = elements.iter();
    let mut token = iter.next();
    while token.is_some() {
        match token.unwrap() {
            &Expression(ref tokens, _) => ret.push(try!(parse_expression(tokens, options))),
            &Tag(ref tokens, _) => ret.push(try!(parse_tag(&mut iter, tokens, options))),
            &Raw(ref x) => ret.push(Box::new(Text::new(&x)) as Box<Renderable>),
        }
        token = iter.next();
    }
    Ok(ret)
}

// creates an expression, which wraps everything that gets rendered
fn parse_expression<'a>(tokens: &Vec<Token>,
                        options: &'a LiquidOptions)
                        -> Result<Box<Renderable + 'a>> {
    match tokens[0] {
        Identifier(ref x) if options.tags.contains_key(&x.to_string()) => {
            Ok(options.tags.get(x).unwrap().initialize(&x, &tokens[1..], options))
        }
        _ => parse_output(tokens),
    }
}

// creates an output, basically a wrapper around values, variables and filters
fn parse_output<'a>(tokens: &Vec<Token>) -> Result<Box<Renderable + 'a>> {
    let entry = match tokens[0] {
        Identifier(ref x) => VarOrVal::Var(Variable::new(&x)),
        StringLiteral(ref x) => VarOrVal::Val(Value::Str(x.to_string())),
        ref x => return Err(Error::Parser(format!("parse_output: {:?} not implemented", x))),
    };

    let mut filters = vec![];
    let mut iter = tokens.iter().peekable();
    iter.next();

    while iter.peek() != None {
        if iter.next().unwrap() != &Pipe {
            return Err(Error::Parser("parse_output: expected a pipe".to_owned()));
        }
        let name = match iter.next() {
            Some(&Identifier(ref name)) => name,
            ref x => return Err(Error::Parser(format!("parse_output: expected an Identifier, got {:?}", x))),
        };
        let mut args = vec![];

        match iter.peek() {
            Some(&&Pipe) | None => {
                filters.push(FilterPrototype::new(&name, args));
                continue;
            }
            _ => (),
        }

        if iter.peek().unwrap() != &&Colon {
            return Err(Error::Parser("parse_output: expected a colon".to_owned()));
        }

        iter.next(); // skip colon

        println!("{:?}", tokens);
        while iter.peek() != None && iter.peek().unwrap() != &&Pipe {
            match iter.next().unwrap() {
                &Comma => continue, // next argument
                &StringLiteral(ref x) => args.push(Value::Str(x.to_string())),
                &NumberLiteral(x) => args.push(Value::Num(x)),
                ref x => return Err(Error::Parser(format!("parse_output: {:?} not implemented", x))),
            }
        }

        filters.push(FilterPrototype::new(&name, args));
    }

    Ok(Box::new(Output::new(entry, filters)) as Box<Renderable>)
}

// a tag can be either a single-element tag or a block, which can contain other
// elements
// and is delimited by a closing tag named {{end + the_name_of_the_tag}}
// tags do not get rendered, but blocks may contain renderable expressions
fn parse_tag<'a>(iter: &mut Iter<Element>,
                 tokens: &Vec<Token>,
                 options: &'a LiquidOptions)
                 -> Result<Box<Renderable + 'a>> {
    match tokens[0] {

        // is a tag
        Identifier(ref x) if options.tags.contains_key(x) => {
            Ok(options.tags.get(x).unwrap().initialize(&x, &tokens[1..], options))
        }

        // is a block
        Identifier(ref x) if options.blocks.contains_key(x) => {
            let end_tag = Identifier("end".to_string() + &x);
            let mut children = vec![];
            loop {
                children.push(match iter.next() {
                    Some(&Tag(ref tokens, _)) if tokens[0] == end_tag => break,
                    None => break,
                    Some(t) => t.clone(),
                })
            }
            options.blocks.get(x).unwrap().initialize(&x, &tokens[1..], children, options)
        }

        ref x => Err(Error::Parser(format!("parse_tag: {:?} not implemented", x))),
    }
}
<commit_msg>Remove debug print statement.<commit_after>use Renderable;
use LiquidOptions;
use value::Value;
use variable::Variable;
use text::Text;
use std::slice::Iter;
use output::Output;
use output::FilterPrototype;
use output::VarOrVal;
use lexer::Token;
use lexer::Token::{Identifier, Colon, Comma, Pipe, StringLiteral, NumberLiteral};
use lexer::Element;
use lexer::Element::{Expression, Tag, Raw};
use error::{Error, Result};

pub fn parse<'a>(elements: &[Element],
                 options: &'a LiquidOptions)
                 -> Result<Vec<Box<Renderable + 'a>>> {
    let mut ret = vec![];
    let mut iter = elements.iter();
    let mut token = iter.next();
    while token.is_some() {
        match token.unwrap() {
            &Expression(ref tokens, _) => ret.push(try!(parse_expression(tokens, options))),
            &Tag(ref tokens, _) => ret.push(try!(parse_tag(&mut iter, tokens, options))),
            &Raw(ref x) => ret.push(Box::new(Text::new(&x)) as Box<Renderable>),
        }
        token = iter.next();
    }
    Ok(ret)
}

// creates an expression, which wraps everything that gets rendered
fn parse_expression<'a>(tokens: &Vec<Token>,
                        options: &'a LiquidOptions)
                        -> Result<Box<Renderable + 'a>> {
    match tokens[0] {
        Identifier(ref x) if options.tags.contains_key(&x.to_string()) => {
            Ok(options.tags.get(x).unwrap().initialize(&x, &tokens[1..], options))
        }
        _ => parse_output(tokens),
    }
}

// creates an output, basically a wrapper around values, variables and filters
fn parse_output<'a>(tokens: &Vec<Token>) -> Result<Box<Renderable + 'a>> {
    let entry = match tokens[0] {
        Identifier(ref x) => VarOrVal::Var(Variable::new(&x)),
        StringLiteral(ref x) => VarOrVal::Val(Value::Str(x.to_string())),
        ref x => return Err(Error::Parser(format!("parse_output: {:?} not implemented", x))),
    };

    let mut filters = vec![];
    let mut iter = tokens.iter().peekable();
    iter.next();

    while iter.peek() != None {
        if iter.next().unwrap() != &Pipe {
            return Err(Error::Parser("parse_output: expected a pipe".to_owned()));
        }
        let name = match iter.next() {
            Some(&Identifier(ref name)) => name,
            ref x => return Err(Error::Parser(format!("parse_output: expected an Identifier, got {:?}", x))),
        };
        let mut args = vec![];

        match iter.peek() {
            Some(&&Pipe) | None => {
                filters.push(FilterPrototype::new(&name, args));
                continue;
            }
            _ => (),
        }

        if iter.peek().unwrap() != &&Colon {
            return Err(Error::Parser("parse_output: expected a colon".to_owned()));
        }

        iter.next(); // skip colon

        while iter.peek() != None && iter.peek().unwrap() != &&Pipe {
            match iter.next().unwrap() {
                &Comma => continue, // next argument
                &StringLiteral(ref x) => args.push(Value::Str(x.to_string())),
                &NumberLiteral(x) => args.push(Value::Num(x)),
                ref x => return Err(Error::Parser(format!("parse_output: {:?} not implemented", x))),
            }
        }

        filters.push(FilterPrototype::new(&name, args));
    }

    Ok(Box::new(Output::new(entry, filters)) as Box<Renderable>)
}

// a tag can be either a single-element tag or a block, which can contain other
// elements
// and is delimited by a closing tag named {{end + the_name_of_the_tag}}
// tags do not get rendered, but blocks may contain renderable expressions
fn parse_tag<'a>(iter: &mut Iter<Element>,
                 tokens: &Vec<Token>,
                 options: &'a LiquidOptions)
                 -> Result<Box<Renderable + 'a>> {
    match tokens[0] {

        // is a tag
        Identifier(ref x) if options.tags.contains_key(x) => {
            Ok(options.tags.get(x).unwrap().initialize(&x, &tokens[1..], options))
        }

        // is a block
        Identifier(ref x) if options.blocks.contains_key(x) => {
            let end_tag = Identifier("end".to_string() + &x);
            let mut children = vec![];
            loop {
                children.push(match iter.next() {
                    Some(&Tag(ref tokens, _)) if tokens[0] == end_tag => break,
                    None => break,
                    Some(t) => t.clone(),
                })
            }
            options.blocks.get(x).unwrap().initialize(&x, &tokens[1..], children, options)
        }

        ref x => Err(Error::Parser(format!("parse_tag: {:?} not implemented", x))),
    }
}
<|endoftext|>


<commit_before>//! This module provides extensible, dynamically typed persistable values for
//! use in the Holmes language and postgres db.

use std::hash::{Hash, Hasher};
use std::sync::Arc;

pub trait HashTO {
  fn hash_to(&self, &mut Hasher);
}

struct HashProxy<'a> {
  pub hasher : &'a mut Hasher
}

impl <'a> Hasher for HashProxy<'a> {
  fn finish(&self) -> u64 {
    self.hasher.finish()
  }
  fn write(&mut self, bytes : &[u8]) {
    self.hasher.write(bytes)
  }
}

impl <T : Hash + Sized> HashTO for T {
  fn hash_to(&self, h : &mut Hasher) {
    self.hash(&mut HashProxy { hasher : h })
  }
}

pub type Type = Arc<self::types::TypeT>;
pub type Value = Arc<self::values::ValueT>;

pub mod types {
  use super::values;
  use super::super::RowIter;
  use std::any::Any;
  use std::fmt;
  use std::sync::Arc;
  use std::hash::{Hash, Hasher};
  use super::HashTO;
  use super::Type;
  use super::Value;

  pub trait TypeT : Sync + Send + HashTO + Any {
    // For a registered type, name() will provide the way to add it to a
    // predicate, and the thing to pattern match against when loading from the
    // db.
    // None will be returned if the type is anonymous, such as a tuple or list.
    fn name(&self) -> Option<&'static str>;
    // Takes in an iterator over the row, then attempts to read a value.
    // Since the underlying .get() will panic, I'm not including an additional
    // error reporting path (for now)
    fn extract(&self, &mut RowIter) -> Value;
    // Generates the database representation of the fields required. For example,
    // for a bitvector this would be
    // vec!["bytea".to_string(), "int64".to_string()]
    // or similar, depending on how you chose to construct the size
    fn repr(&self) -> Vec<::std::string::String>;
    // Escape hatch
    fn inner(&self) -> &Any;
    // Check equality
    // This should be symmetric, but we have no way to enforce it within the
    // type system of rust.
    fn inner_eq(&self, &TypeT) -> bool;
  }

  impl Hash for TypeT {
    fn hash<H : Hasher>(&self, hasher : &mut H) {
      self.hash_to(hasher)
    }
  }

  impl fmt::Debug for TypeT {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
      write!(f, "[Name: {:?}, Repr: {:?}]", self.name(), self.repr())
    }
  }

  impl Eq for TypeT {}
  impl PartialEq for TypeT {
    fn eq(&self, t : &TypeT) -> bool {
      self.inner_eq(t)
    }
  }

  #[derive(Debug,Clone,Hash)]
  pub struct Tuple {
    elements : Vec<Type>
  }

  impl Tuple {
    pub fn new(elems : Vec<Type>) -> Arc<Self> {
      Arc::new(Tuple { elements : elems })
    }
  }

  impl TypeT for Tuple {
    fn name(&self) -> Option<&'static str> {
      None
    }
    fn extract(&self, rows : &mut RowIter) -> Value {
      values::Tuple::new(self.elements.iter().map(|elem| {elem.extract(rows)}).collect())
    }
    fn repr(&self) -> Vec<::std::string::String> {
      self.elements.iter().flat_map(|elem| {elem.repr()}).collect()
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &TypeT) -> bool {
      match other.inner().downcast_ref::<Self>() {
        Some(tup) => self.elements == tup.elements,
        // If the target is not a tuple, our types are not equal.
        None => false
      }
    }
  }

  #[derive(Debug,Clone,Hash)]
  pub struct List {
    elem : Type
  }

  impl List {
    pub fn new(elem : Type) -> Arc<Self> {
      Arc::new(List { elem : elem })
    }
  }

  impl TypeT for List {
    fn name(&self) -> Option<&'static str> {
      None
    }
    fn extract(&self, _rows : &mut RowIter) -> Value {
      panic!("List support disabled, will be re-enabled via arrays maybe")
    }
    fn repr(&self) -> Vec<::std::string::String> {
      panic!("List support disabled, will be re-enabled via arrays maybe")
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &TypeT) -> bool {
      match other.inner().downcast_ref::<Self>() {
        Some(ref tup) => self.elem == tup.elem.clone(),
        // If the target is not a tuple, our types are not equal.
        None => false
      }
    }
  }

  pub fn default_types() -> Vec<Type> {
    vec![Arc::new(UInt64), Arc::new(String), Arc::new(Bytes)]
  }

  #[derive(Debug,Clone,Hash)]
  pub struct UInt64;

  impl TypeT for UInt64 {
    fn name(&self) -> Option<&'static str> {
      Some("uint64")
    }
    fn extract(&self, rows : &mut RowIter) -> Value {
      let x : i64 = rows.next().unwrap();
      values::UInt64::new(x as u64)
    }
    fn repr(&self) -> Vec<::std::string::String> {
      vec!["int8".to_string()]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &TypeT) -> bool {
      match other.inner().downcast_ref::<Self>() {
        Some(_) => true,
        _ => false
      }
    }
  }

  #[derive(Debug,Clone,Hash)]
  pub struct String;

  impl TypeT for String {
    fn name(&self) -> Option<&'static str> {
      Some("string")
    }
    fn extract(&self, rows : &mut RowIter) -> Value {
      values::String::new(rows.next().unwrap())
    }
    fn repr(&self) -> Vec<::std::string::String> {
      vec!["varchar".to_string()]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &TypeT) -> bool {
      match other.inner().downcast_ref::<Self>() {
        Some(_) => true,
        _ => false
      }
    }
  }

  #[derive(Debug,Clone,Hash)]
  pub struct Bytes;

  impl TypeT for Bytes {
    fn name(&self) -> Option<&'static str> {
      Some("bytes")
    }
    fn extract(&self, rows : &mut RowIter) -> Value {
      values::Bytes::new(rows.next().unwrap())
    }
    fn repr(&self) -> Vec<::std::string::String> {
      vec!["bytea".to_string()]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &TypeT) -> bool {
      match other.inner().downcast_ref::<Self>() {
        Some(_) => true,
        _ => false
      }
    }
  }

}

pub mod values {
  use postgres::types::ToSql;
  use std::any::Any;
  use super::HashTO;
  use std::sync::Arc;
  use std::hash::{Hash, Hasher};
  use std::fmt;
  use super::Type;
  use super::Value;
  use super::types;

  pub trait ValueT : Sync + Send + HashTO + fmt::Debug + Any {
    // Returns the type, needed if you want to do type checking, or tuple values
    fn type_(&self) -> Type;
    // Get a rust dynamic type, to be used by someone who was typed in the holmes
    // language, and so knows what they're actually getting
    fn get(&self) -> &Any;
    // Converts the value into a list of ToSql trait objects to allow for
    // insertion into the database via a prepared query
    fn to_sql(&self) -> Vec<&ToSql>;
    // Escape hatch
    fn inner(&self) -> &Any;
    // Used to test equality, to implement PartialEq
    fn inner_eq(&self, other : &ValueT) -> bool;
  }

  impl Hash for ValueT {
    fn hash<H : Hasher>(&self, hasher : &mut H) {
      self.hash_to(hasher)
    }
  }

  pub trait ToValue {
    fn to_value(self) -> Value;
  }

  impl Eq for ValueT {}
  impl PartialEq for ValueT {
    fn eq(&self, other : &ValueT) -> bool {
      self.inner_eq(other)
    }
  }

  #[derive(Debug,Clone,PartialEq,Hash)]
  pub struct List {
    elements : Vec<Value>,
  }

  impl ValueT for List {
    fn type_(&self) -> Type {
      match self.elements.first() {
        Some(e) => types::List::new(e.type_()),
        //TODO have some kind of poly type to default to? Equal to everything?
        None => types::List::new(Arc::new(types::UInt64))
      }
    }
    fn get(&self) -> &Any {
      &self.elements as &Any
    }
    fn to_sql(&self) -> Vec<&ToSql> {
      panic!("List SQL disabled")
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &ValueT) -> bool {
      let other_typed : &List = match other.inner().downcast_ref::<Self>() {
        Some(x) => x,
        None => return false
      };
      self == other_typed
    }
  }

  impl List {
    pub fn new(elements : Vec<Value>) -> Arc<Self> {
      Arc::new(List { elements : elements })
    }
  }

  #[derive(Debug,Clone,PartialEq,Hash)]
  pub struct Tuple {
    elements : Vec<Value>,
  }

  impl ValueT for Tuple {
    fn type_(&self) -> Type {
      types::Tuple::new(self.elements.iter().map(|val| {val.type_()}).collect())
    }
    fn get(&self) -> &Any {
      &self.elements as &Any
    }
    fn to_sql(&self) -> Vec<&ToSql> {
      self.elements.iter().flat_map(|val| val.to_sql()).collect()
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &ValueT) -> bool {
      let other_typed : &Tuple = match other.inner().downcast_ref::<Self>() {
        Some(x) => x,
        None => return false
      };
      self == other_typed
    }
  }

  impl Tuple {
    pub fn new(elements : Vec<Value>) -> Arc<Self> {
      Arc::new(Tuple { elements : elements })
    }
  }

  #[derive(Debug,PartialEq,Hash)]
  pub struct UInt64 {
    val : u64,
    sql : i64
  }

  impl ToValue for u64 {
    fn to_value(self) -> Value {
      UInt64::new(self)
    }
  }
  impl ToValue for ::std::string::String {
    fn to_value(self) -> Value {
      String::new(self)
    }
  }
  impl ToValue for Vec<u8> {
    fn to_value(self) -> Value {
      Bytes::new(self)
    }
  }
  impl ToValue for &'static str {
    fn to_value(self) -> Value {
      String::new(self.to_string())
    }
  }

  impl ValueT for UInt64 {
    fn type_(&self) -> Type {
      Arc::new(types::UInt64)
    }
    fn get(&self) -> &Any {
      &self.val as &Any
    }
    fn to_sql(&self) -> Vec<&ToSql> {
      vec![&self.sql]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &ValueT) -> bool {
      let other_typed : &UInt64 = match other.inner().downcast_ref::<Self>() {
        Some(x) => x,
        None => return false
      };
      self == other_typed
    }
  }

  impl UInt64 {
    pub fn new(val : u64) -> Arc<Self> {
      Arc::new(UInt64 { val : val, sql : val as i64 })
    }
  }

  #[derive(Debug,PartialEq,Hash)]
  pub struct String {
    val : ::std::string::String,
  }

  impl ValueT for String {
    fn type_(&self) -> Type {
      Arc::new(types::String)
    }
    fn get(&self) -> &Any {
      &self.val as &Any
    }
    fn to_sql(&self) -> Vec<&ToSql> {
      vec![&self.val as &ToSql]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &ValueT) -> bool {
      let other_typed : &String = match other.inner().downcast_ref::<Self>() {
        Some(x) => x,
        None => return false
      };
      self == other_typed
    }
  }

  impl String {
    pub fn new(val : ::std::string::String) -> Arc<Self> {
      Arc::new(String { val : val })
    }
  }

  #[derive(Debug,PartialEq,Hash)]
  pub struct Bytes {
    val : Vec<u8>,
  }

  impl ValueT for Bytes {
    fn type_(&self) -> Type {
      Arc::new(types::Bytes)
    }
    fn get(&self) -> &Any {
      &self.val as &Any
    }
    fn to_sql(&self) -> Vec<&ToSql> {
      vec![&self.val as &ToSql]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &ValueT) -> bool {
      let other_typed : &Bytes = match other.inner().downcast_ref::<Self>() {
        Some(x) => x,
        None => return false
      };
      self == other_typed
    }
  }

  impl Bytes {
    pub fn new(val : Vec<u8>) -> Arc<Self> {
      Arc::new(Bytes { val : val })
    }
  }

}
<commit_msg>Document dynamic types<commit_after>//! This module provides extensible, dynamically typed persistable values for
//! use in the Holmes language and postgres db.

use std::hash::{Hash, Hasher};
use std::sync::Arc;

/// `HashTO` is a Trait Object-safe version of the Hash trait, using a
/// reference to a `Hasher` rather than a polymorphic one in order to allow
/// construction of trait objects.
///
/// `HashTO` is implemented automatically for any type implementing `Hash`,
/// allowing Trait Objects to implement `Hash`. For example:
///
/// ```
/// use holmes::pg::dyn::HashTO;
/// use std::hash::{Hash, Hasher};
/// trait Foo : HashTO {}
/// #[derive(Hash)]
/// struct Bar;
/// impl Foo for Bar {}
/// impl Hash for Foo {
///   fn hash<H : Hasher>(&self, hasher : &mut H) {
///     self.hash_to(hasher)
///   }
/// }
/// ```
///
/// This trick allows `Value` and `Type` trait objects to be used as keys in
/// maps by having types implementing the `ValueT` or `TypeT` interface derive
/// `Hash`.
pub trait HashTO {
  fn hash_to(&self, &mut Hasher);
}

struct HashProxy<'a> {
  pub hasher : &'a mut Hasher
}

impl <'a> Hasher for HashProxy<'a> {
  fn finish(&self) -> u64 {
    self.hasher.finish()
  }
  fn write(&mut self, bytes : &[u8]) {
    self.hasher.write(bytes)
  }
}

impl <T : Hash> HashTO for T {
  fn hash_to(&self, h : &mut Hasher) {
    self.hash(&mut HashProxy { hasher : h })
  }
}

/// Represents the type of a dynamic value as a threadsafe trait object.
pub type Type = Arc<self::types::TypeT>;
/// Represents a dynamic value as a threadsafe trait object.
pub type Value = Arc<self::values::ValueT>;

pub mod types {
  //! This module defines the trait new types must implement, along with
  //! several core types to avoid the need to rewrite basic types every time.
  //! It is heavily codependent on the `values` module.
  use super::values;
  use super::super::RowIter;
  use std::any::Any;
  use std::fmt;
  use std::sync::Arc;
  use std::hash::{Hash, Hasher};
  use super::HashTO;
  use super::Type;
  use super::Value;

  /// The TypeT trait defines the interface a new Holmes type must implement
  /// to be registered.
  pub trait TypeT : Sync + Send + HashTO + Any {
    /// For a registered type, name() will provide the way to add it to a
    /// predicate, and the thing to pattern match against when loading from the
    /// db.
    /// None will be returned if the type is anonymous, such as a tuple or
    /// list.
    fn name(&self) -> Option<&'static str>;
    /// Takes in an iterator over the row, then attempts to read a value of the
    /// type specified.
    fn extract(&self, &mut RowIter) -> Value;
    /// Generates the database representation of the fields required. For
    /// example,
    /// for a bitvector this would be
    /// ```
    /// vec!["bytea".to_string(), "int64".to_string()]
    /// ```
    /// or similar, depending on how you chose to construct the size.
    fn repr(&self) -> Vec<::std::string::String>;
    /// Returns a dynamic representation of the trait object.
    ///
    /// Trait objects cannot be cast to other trait objects, even if they
    /// implement the other trait necessarily. In order to access functions
    /// under the `Any` trait, I have the non-trait-object implementation
    /// provide access to its &Any representation.
    fn inner(&self) -> &Any;
    /// Check equality
    ///
    /// Similar to `inner`, `inner_eq` exports a `PartialEq` instance from
    /// the underlying type.
    fn inner_eq(&self, &TypeT) -> bool;
  }

  impl Hash for TypeT {
    fn hash<H : Hasher>(&self, hasher : &mut H) {
      self.hash_to(hasher)
    }
  }

  impl fmt::Debug for TypeT {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
      write!(f, "[Name: {:?}, Repr: {:?}]", self.name(), self.repr())
    }
  }

  impl Eq for TypeT {}
  impl PartialEq for TypeT {
    fn eq(&self, t : &TypeT) -> bool {
      self.inner_eq(t)
    }
  }

  /// A tuple of other `Type`s
  /// This type is anonymous.
  #[derive(Debug,Clone,Hash)]
  pub struct Tuple {
    elements : Vec<Type>
  }

  impl Tuple {
    /// Construct a new tuple from a vector of other types
    pub fn new(elems : Vec<Type>) -> Arc<Self> {
      Arc::new(Tuple { elements : elems })
    }
  }

  impl TypeT for Tuple {
    fn name(&self) -> Option<&'static str> {
      None
    }
    fn extract(&self, rows : &mut RowIter) -> Value {
      values::Tuple::new(self.elements.iter().map(|elem| {elem.extract(rows)}).collect())
    }
    fn repr(&self) -> Vec<::std::string::String> {
      self.elements.iter().flat_map(|elem| {elem.repr()}).collect()
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &TypeT) -> bool {
      match other.inner().downcast_ref::<Self>() {
        Some(tup) => self.elements == tup.elements,
        // If the target is not a tuple, our types are not equal.
        None => false
      }
    }
  }

  /// A list of another `Type`
  /// This type is anonymous.
  #[derive(Debug,Clone,Hash)]
  pub struct List {
    elem : Type
  }

  impl List {
    /// Constructs a list type of the provided element type
    pub fn new(elem : Type) -> Arc<Self> {
      Arc::new(List { elem : elem })
    }
  }

  impl TypeT for List {
    fn name(&self) -> Option<&'static str> {
      None
    }
    fn extract(&self, _rows : &mut RowIter) -> Value {
      panic!("List support disabled, will be re-enabled via arrays maybe")
    }
    fn repr(&self) -> Vec<::std::string::String> {
      panic!("List support disabled, will be re-enabled via arrays maybe")
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &TypeT) -> bool {
      match other.inner().downcast_ref::<Self>() {
        Some(ref tup) => self.elem == tup.elem.clone(),
        // If the target is not a tuple, our types are not equal.
        None => false
      }
    }
  }

  /// Provides a list of provided named types for use by the database
  /// as a default set of types.
  pub fn default_types() -> Vec<Type> {
    vec![Arc::new(UInt64), Arc::new(String), Arc::new(Bytes)]
  }

  /// Unsigned 64-bit int type
  #[derive(Debug,Clone,Hash)]
  pub struct UInt64;

  impl TypeT for UInt64 {
    fn name(&self) -> Option<&'static str> {
      Some("uint64")
    }
    fn extract(&self, rows : &mut RowIter) -> Value {
      let x : i64 = rows.next().unwrap();
      values::UInt64::new(x as u64)
    }
    fn repr(&self) -> Vec<::std::string::String> {
      vec!["int8".to_string()]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &TypeT) -> bool {
      match other.inner().downcast_ref::<Self>() {
        Some(_) => true,
        _ => false
      }
    }
  }

  /// `String` type
  /// Use this for text. If you want to store a buffer, use `Bytes` instead.
  #[derive(Debug,Clone,Hash)]
  pub struct String;

  impl TypeT for String {
    fn name(&self) -> Option<&'static str> {
      Some("string")
    }
    fn extract(&self, rows : &mut RowIter) -> Value {
      values::String::new(rows.next().unwrap())
    }
    fn repr(&self) -> Vec<::std::string::String> {
      vec!["varchar".to_string()]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &TypeT) -> bool {
      match other.inner().downcast_ref::<Self>() {
        Some(_) => true,
        _ => false
      }
    }
  }

  /// `Bytes` is for storing raw data
  /// If you want to store text, use the `String` type.
  #[derive(Debug,Clone,Hash)]
  pub struct Bytes;

  impl TypeT for Bytes {
    fn name(&self) -> Option<&'static str> {
      Some("bytes")
    }
    fn extract(&self, rows : &mut RowIter) -> Value {
      values::Bytes::new(rows.next().unwrap())
    }
    fn repr(&self) -> Vec<::std::string::String> {
      vec!["bytea".to_string()]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &TypeT) -> bool {
      match other.inner().downcast_ref::<Self>() {
        Some(_) => true,
        _ => false
      }
    }
  }

}

pub mod values {
  //! This module defines the trait new values must implement, along with
  //! several core values to instantiate the basic types provided in `types`.
  //! It is heavily codependent on the `values` module.
  use postgres::types::ToSql;
  use std::any::Any;
  use super::HashTO;
  use std::sync::Arc;
  use std::hash::{Hash, Hasher};
  use std::fmt;
  use super::Type;
  use super::Value;
  use super::types;

  /// This trait defines the interface any value must implement in order to be
  /// used in the Holmes language.
  pub trait ValueT : Sync + Send + HashTO + fmt::Debug + Any {
    /// Returns the type of the value
    /// This is needed if to do type checking, or tuple values
    fn type_(&self) -> Type;
    /// Get a rust dynamic type version of the value contained.
    ///
    /// Since Holmes is a typed language, the user of this function should
    /// know what to expect and be able to cast from Any into it.
    fn get(&self) -> &Any;
    /// Converts the value into a list of ToSql trait objects to allow for
    /// insertion into the database via a prepared query
    fn to_sql(&self) -> Vec<&ToSql>;
    /// Returns a dynamic representation of the trait object.
    ///
    /// Trait objects cannot be cast to other trait objects, even if they
    /// implement the other trait necessarily. In order to access functions
    /// under the `Any` trait, I have the non-trait-object implementation
    /// provide access to its &Any representation.
    fn inner(&self) -> &Any;
    /// Check equality
    ///
    /// Similar to `inner`, `inner_eq` exports a `PartialEq` instance from
    /// the underlying type.
    fn inner_eq(&self, other : &ValueT) -> bool;
  }

  impl Hash for ValueT {
    fn hash<H : Hasher>(&self, hasher : &mut H) {
      self.hash_to(hasher)
    }
  }

  /// Represents the transformability of some type into a dynamic value.
  ///
  /// This is useful both as an easy way to turn Rust values into Holmes
  /// values, and to allow for the use of literals in the macro DSL system.
  pub trait ToValue {
    fn to_value(self) -> Value;
  }

  impl Eq for ValueT {}
  impl PartialEq for ValueT {
    fn eq(&self, other : &ValueT) -> bool {
      self.inner_eq(other)
    }
  }

  /// A list of samely typed values.
  #[derive(Debug,Clone,PartialEq,Hash)]
  pub struct List {
    elements : Vec<Value>,
  }

  impl ValueT for List {
    fn type_(&self) -> Type {
      match self.elements.first() {
        Some(e) => types::List::new(e.type_()),
        //TODO have some kind of poly type to default to? Equal to everything?
        None => types::List::new(Arc::new(types::UInt64))
      }
    }
    fn get(&self) -> &Any {
      &self.elements as &Any
    }
    fn to_sql(&self) -> Vec<&ToSql> {
      panic!("List SQL disabled")
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &ValueT) -> bool {
      let other_typed : &List = match other.inner().downcast_ref::<Self>() {
        Some(x) => x,
        None => return false
      };
      self == other_typed
    }
  }

  impl List {
    /// Create a dynamic `List` value from a list of `Value`s
    pub fn new(elements : Vec<Value>) -> Arc<Self> {
      Arc::new(List { elements : elements })
    }
  }

  /// A tuple of potentially differently typed values.
  #[derive(Debug,Clone,PartialEq,Hash)]
  pub struct Tuple {
    elements : Vec<Value>,
  }

  impl ValueT for Tuple {
    fn type_(&self) -> Type {
      types::Tuple::new(self.elements.iter().map(|val| {val.type_()}).collect())
    }
    fn get(&self) -> &Any {
      &self.elements as &Any
    }
    fn to_sql(&self) -> Vec<&ToSql> {
      self.elements.iter().flat_map(|val| val.to_sql()).collect()
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &ValueT) -> bool {
      let other_typed : &Tuple = match other.inner().downcast_ref::<Self>() {
        Some(x) => x,
        None => return false
      };
      self == other_typed
    }
  }

  impl Tuple {
    /// Create a dynamic `Tuple` value from a vector of its components.
    pub fn new(elements : Vec<Value>) -> Arc<Self> {
      Arc::new(Tuple { elements : elements })
    }
  }

  /// Holds an unsigned 64-bit int
  #[derive(Debug,PartialEq,Hash)]
  pub struct UInt64 {
    val : u64,
    sql : i64
  }

  impl ToValue for u64 {
    fn to_value(self) -> Value {
      UInt64::new(self)
    }
  }
  impl ToValue for ::std::string::String {
    fn to_value(self) -> Value {
      String::new(self)
    }
  }
  impl ToValue for Vec<u8> {
    fn to_value(self) -> Value {
      Bytes::new(self)
    }
  }
  impl ToValue for &'static str {
    fn to_value(self) -> Value {
      String::new(self.to_string())
    }
  }

  impl ValueT for UInt64 {
    fn type_(&self) -> Type {
      Arc::new(types::UInt64)
    }
    fn get(&self) -> &Any {
      &self.val as &Any
    }
    fn to_sql(&self) -> Vec<&ToSql> {
      vec![&self.sql]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &ValueT) -> bool {
      let other_typed : &UInt64 = match other.inner().downcast_ref::<Self>() {
        Some(x) => x,
        None => return false
      };
      self == other_typed
    }
  }

  impl UInt64 {
    /// Creates Holmes value holding an unsigned 64-bit integer
    pub fn new(val : u64) -> Arc<Self> {
      Arc::new(UInt64 { val : val, sql : val as i64 })
    }
  }

  /// Holds text
  #[derive(Debug,PartialEq,Hash)]
  pub struct String {
    val : ::std::string::String,
  }

  impl ValueT for String {
    fn type_(&self) -> Type {
      Arc::new(types::String)
    }
    fn get(&self) -> &Any {
      &self.val as &Any
    }
    fn to_sql(&self) -> Vec<&ToSql> {
      vec![&self.val as &ToSql]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &ValueT) -> bool {
      let other_typed : &String = match other.inner().downcast_ref::<Self>() {
        Some(x) => x,
        None => return false
      };
      self == other_typed
    }
  }

  impl String {
    /// Creates a Holmes value holding a `String`
    pub fn new(val : ::std::string::String) -> Arc<Self> {
      Arc::new(String { val : val })
    }
  }

  /// Holds raw data
  #[derive(Debug,PartialEq,Hash)]
  pub struct Bytes {
    val : Vec<u8>,
  }

  impl ValueT for Bytes {
    fn type_(&self) -> Type {
      Arc::new(types::Bytes)
    }
    fn get(&self) -> &Any {
      &self.val as &Any
    }
    fn to_sql(&self) -> Vec<&ToSql> {
      vec![&self.val as &ToSql]
    }
    fn inner(&self) -> &Any {
      self as &Any
    }
    fn inner_eq(&self, other : &ValueT) -> bool {
      let other_typed : &Bytes = match other.inner().downcast_ref::<Self>() {
        Some(x) => x,
        None => return false
      };
      self == other_typed
    }
  }

  impl Bytes {
    /// Creates a new Holmes value holding raw data.
    pub fn new(val : Vec<u8>) -> Arc<Self> {
      Arc::new(Bytes { val : val })
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

pub use self::RelationDir::*;
use self::TypeVariableValue::*;
use self::UndoEntry::*;

use middle::ty::{self, Ty};
use std::cmp::min;
use std::marker::PhantomData;
use std::mem;
use std::u32;
use rustc_data_structures::snapshot_vec as sv;

pub struct TypeVariableTable<'tcx> {
    values: sv::SnapshotVec<Delegate<'tcx>>,
}

struct TypeVariableData<'tcx> {
    value: TypeVariableValue<'tcx>,
    diverging: bool
}

enum TypeVariableValue<'tcx> {
    Known(Ty<'tcx>),
    Bounded {
        relations: Vec<Relation>,
        default: Option<Default<'tcx>>
    }
}

// We will use this to store the required information to recapitulate what happened when
// an error occurs.
#[derive(Clone)]
pub struct Default<'tcx> {
    pub ty: Ty<'tcx>
}

pub struct Snapshot {
    snapshot: sv::Snapshot
}

enum UndoEntry {
    // The type of the var was specified.
    SpecifyVar(ty::TyVid, Vec<Relation>),
    Relate(ty::TyVid, ty::TyVid),
}

struct Delegate<'tcx>(PhantomData<&'tcx ()>);

type Relation = (RelationDir, ty::TyVid);

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum RelationDir {
    SubtypeOf, SupertypeOf, EqTo, BiTo
}

impl RelationDir {
    fn opposite(self) -> RelationDir {
        match self {
            SubtypeOf => SupertypeOf,
            SupertypeOf => SubtypeOf,
            EqTo => EqTo,
            BiTo => BiTo,
        }
    }
}

impl<'tcx> TypeVariableTable<'tcx> {
    pub fn new() -> TypeVariableTable<'tcx> {
        TypeVariableTable { values: sv::SnapshotVec::new() }
    }

    fn relations<'a>(&'a mut self, a: ty::TyVid) -> &'a mut Vec<Relation> {
        relations(self.values.get_mut(a.index as usize))
    }

    pub fn default(&self, vid: ty::TyVid) -> Option<Default<'tcx>> {
        match &self.values.get(vid.index as usize).value {
            &Known(_) => None,
            &Bounded { ref default, .. } => default.clone()
        }
    }

    pub fn var_diverges<'a>(&'a self, vid: ty::TyVid) -> bool {
        self.values.get(vid.index as usize).diverging
    }

    /// Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`.
    ///
    /// Precondition: neither `a` nor `b` are known.
    pub fn relate_vars(&mut self, a: ty::TyVid, dir: RelationDir, b: ty::TyVid) {
        if a != b {
            self.relations(a).push((dir, b));
            self.relations(b).push((dir.opposite(), a));
            self.values.record(Relate(a, b));
        }
    }

    /// Instantiates `vid` with the type `ty` and then pushes an entry onto `stack` for each of the
    /// relations of `vid` to other variables. The relations will have the form `(ty, dir, vid1)`
    /// where `vid1` is some other variable id.
    pub fn instantiate_and_push(
        &mut self,
        vid: ty::TyVid,
        ty: Ty<'tcx>,
        stack: &mut Vec<(Ty<'tcx>, RelationDir, ty::TyVid)>)
    {
        let old_value = {
            let value_ptr = &mut self.values.get_mut(vid.index as usize).value;
            mem::replace(value_ptr, Known(ty))
        };

        let relations = match old_value {
            Bounded { relations, .. } => relations,
            Known(_) => panic!("Asked to instantiate variable that is \
                               already instantiated")
        };

        for &(dir, vid) in &relations {
            stack.push((ty, dir, vid));
        }

        self.values.record(SpecifyVar(vid, relations));
    }

    pub fn new_var(&mut self,
                   diverging: bool,
                   default: Option<Default<'tcx>>) -> ty::TyVid {
        let index = self.values.push(TypeVariableData {
            value: Bounded { relations: vec![], default: default },
            diverging: diverging
        });
        ty::TyVid { index: index as u32 }
    }

    pub fn probe(&self, vid: ty::TyVid) -> Option<Ty<'tcx>> {
        match self.values.get(vid.index as usize).value {
            Bounded { .. } => None,
            Known(t) => Some(t)
        }
    }

    pub fn replace_if_possible(&self, t: Ty<'tcx>) -> Ty<'tcx> {
        match t.sty {
            ty::TyInfer(ty::TyVar(v)) => {
                match self.probe(v) {
                    None => t,
                    Some(u) => u
                }
            }
            _ => t,
        }
    }

    pub fn snapshot(&mut self) -> Snapshot {
        Snapshot { snapshot: self.values.start_snapshot() }
    }

    pub fn rollback_to(&mut self, s: Snapshot) {
        self.values.rollback_to(s.snapshot);
    }

    pub fn commit(&mut self, s: Snapshot) {
        self.values.commit(s.snapshot);
    }

    pub fn types_escaping_snapshot(&self, s: &Snapshot) -> Vec<Ty<'tcx>> {
        /*!
         * Find the set of type variables that existed *before* `s`
         * but which have only been unified since `s` started, and
         * return the types with which they were unified. So if we had
         * a type variable `V0`, then we started the snapshot, then we
         * created a type variable `V1`, unifed `V0` with `T0`, and
         * unified `V1` with `T1`, this function would return `{T0}`.
         */

        let mut new_elem_threshold = u32::MAX;
        let mut escaping_types = Vec::new();
        let actions_since_snapshot = self.values.actions_since_snapshot(&s.snapshot);
        debug!("actions_since_snapshot.len() = {}", actions_since_snapshot.len());
        for action in actions_since_snapshot {
            match *action {
                sv::UndoLog::NewElem(index) => {
                    // if any new variables were created during the
                    // snapshot, remember the lower index (which will
                    // always be the first one we see). Note that this
                    // action must precede those variables being
                    // specified.
                    new_elem_threshold = min(new_elem_threshold, index as u32);
                    debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold);
                }

                sv::UndoLog::Other(SpecifyVar(vid, _)) => {
                    if vid.index < new_elem_threshold {
                        // quick check to see if this variable was
                        // created since the snapshot started or not.
                        let escaping_type = self.probe(vid).unwrap();
                        escaping_types.push(escaping_type);
                    }
                    debug!("SpecifyVar({:?}) new_elem_threshold={}", vid, new_elem_threshold);
                }

                _ => { }
            }
        }

        escaping_types
    }

    pub fn unsolved_variables(&self) -> Vec<ty::TyVid> {
        self.values
            .iter()
            .enumerate()
            .filter_map(|(i, value)| match &value.value {
                &TypeVariableValue::Known(_) => None,
                &TypeVariableValue::Bounded { .. } => Some(ty::TyVid { index: i as u32 })
            })
            .collect()
    }
}

impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
    type Value = TypeVariableData<'tcx>;
    type Undo = UndoEntry;

    fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: UndoEntry) {
        match action {
            SpecifyVar(vid, relations) => {
                values[vid.index as usize].value = Bounded { relations: relations, default: None };
            }

            Relate(a, b) => {
                relations(&mut (*values)[a.index as usize]).pop();
                relations(&mut (*values)[b.index as usize]).pop();
            }
        }
    }
}

fn relations<'a>(v: &'a mut TypeVariableData) -> &'a mut Vec<Relation> {
    match v.value {
        Known(_) => panic!("var_sub_var: variable is known"),
        Bounded { ref mut relations, .. } => relations
    }
}
<commit_msg>Fix bug with defaults not being restored<commit_after>// Copyright 2014 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.

pub use self::RelationDir::*;
use self::TypeVariableValue::*;
use self::UndoEntry::*;

use middle::ty::{self, Ty};
use std::cmp::min;
use std::marker::PhantomData;
use std::mem;
use std::u32;
use rustc_data_structures::snapshot_vec as sv;

pub struct TypeVariableTable<'tcx> {
    values: sv::SnapshotVec<Delegate<'tcx>>,
}

struct TypeVariableData<'tcx> {
    value: TypeVariableValue<'tcx>,
    diverging: bool
}

enum TypeVariableValue<'tcx> {
    Known(Ty<'tcx>),
    Bounded {
        relations: Vec<Relation>,
        default: Option<Default<'tcx>>
    }
}

// We will use this to store the required information to recapitulate what happened when
// an error occurs.
#[derive(Clone)]
pub struct Default<'tcx> {
    pub ty: Ty<'tcx>
}

pub struct Snapshot {
    snapshot: sv::Snapshot
}

enum UndoEntry<'tcx> {
    // The type of the var was specified.
    SpecifyVar(ty::TyVid, Vec<Relation>, Option<Default<'tcx>>),
    Relate(ty::TyVid, ty::TyVid),
}

struct Delegate<'tcx>(PhantomData<&'tcx ()>);

type Relation = (RelationDir, ty::TyVid);

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum RelationDir {
    SubtypeOf, SupertypeOf, EqTo, BiTo
}

impl RelationDir {
    fn opposite(self) -> RelationDir {
        match self {
            SubtypeOf => SupertypeOf,
            SupertypeOf => SubtypeOf,
            EqTo => EqTo,
            BiTo => BiTo,
        }
    }
}

impl<'tcx> TypeVariableTable<'tcx> {
    pub fn new() -> TypeVariableTable<'tcx> {
        TypeVariableTable { values: sv::SnapshotVec::new() }
    }

    fn relations<'a>(&'a mut self, a: ty::TyVid) -> &'a mut Vec<Relation> {
        relations(self.values.get_mut(a.index as usize))
    }

    pub fn default(&self, vid: ty::TyVid) -> Option<Default<'tcx>> {
        match &self.values.get(vid.index as usize).value {
            &Known(_) => None,
            &Bounded { ref default, .. } => default.clone()
        }
    }

    pub fn var_diverges<'a>(&'a self, vid: ty::TyVid) -> bool {
        self.values.get(vid.index as usize).diverging
    }

    /// Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`.
    ///
    /// Precondition: neither `a` nor `b` are known.
    pub fn relate_vars(&mut self, a: ty::TyVid, dir: RelationDir, b: ty::TyVid) {
        if a != b {
            self.relations(a).push((dir, b));
            self.relations(b).push((dir.opposite(), a));
            self.values.record(Relate(a, b));
        }
    }

    /// Instantiates `vid` with the type `ty` and then pushes an entry onto `stack` for each of the
    /// relations of `vid` to other variables. The relations will have the form `(ty, dir, vid1)`
    /// where `vid1` is some other variable id.
    pub fn instantiate_and_push(
        &mut self,
        vid: ty::TyVid,
        ty: Ty<'tcx>,
        stack: &mut Vec<(Ty<'tcx>, RelationDir, ty::TyVid)>)
    {
        let old_value = {
            let value_ptr = &mut self.values.get_mut(vid.index as usize).value;
            mem::replace(value_ptr, Known(ty))
        };

        let (relations, default) = match old_value {
            Bounded { relations, default } => (relations, default),
            Known(_) => panic!("Asked to instantiate variable that is \
                               already instantiated")
        };

        for &(dir, vid) in &relations {
            stack.push((ty, dir, vid));
        }

        self.values.record(SpecifyVar(vid, relations, default));
    }

    pub fn new_var(&mut self,
                   diverging: bool,
                   default: Option<Default<'tcx>>) -> ty::TyVid {
        let index = self.values.push(TypeVariableData {
            value: Bounded { relations: vec![], default: default },
            diverging: diverging
        });
        ty::TyVid { index: index as u32 }
    }

    pub fn probe(&self, vid: ty::TyVid) -> Option<Ty<'tcx>> {
        match self.values.get(vid.index as usize).value {
            Bounded { .. } => None,
            Known(t) => Some(t)
        }
    }

    pub fn replace_if_possible(&self, t: Ty<'tcx>) -> Ty<'tcx> {
        match t.sty {
            ty::TyInfer(ty::TyVar(v)) => {
                match self.probe(v) {
                    None => t,
                    Some(u) => u
                }
            }
            _ => t,
        }
    }

    pub fn snapshot(&mut self) -> Snapshot {
        Snapshot { snapshot: self.values.start_snapshot() }
    }

    pub fn rollback_to(&mut self, s: Snapshot) {
        self.values.rollback_to(s.snapshot);
    }

    pub fn commit(&mut self, s: Snapshot) {
        self.values.commit(s.snapshot);
    }

    pub fn types_escaping_snapshot(&self, s: &Snapshot) -> Vec<Ty<'tcx>> {
        /*!
         * Find the set of type variables that existed *before* `s`
         * but which have only been unified since `s` started, and
         * return the types with which they were unified. So if we had
         * a type variable `V0`, then we started the snapshot, then we
         * created a type variable `V1`, unifed `V0` with `T0`, and
         * unified `V1` with `T1`, this function would return `{T0}`.
         */

        let mut new_elem_threshold = u32::MAX;
        let mut escaping_types = Vec::new();
        let actions_since_snapshot = self.values.actions_since_snapshot(&s.snapshot);
        debug!("actions_since_snapshot.len() = {}", actions_since_snapshot.len());
        for action in actions_since_snapshot {
            match *action {
                sv::UndoLog::NewElem(index) => {
                    // if any new variables were created during the
                    // snapshot, remember the lower index (which will
                    // always be the first one we see). Note that this
                    // action must precede those variables being
                    // specified.
                    new_elem_threshold = min(new_elem_threshold, index as u32);
                    debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold);
                }

                sv::UndoLog::Other(SpecifyVar(vid, _, _)) => {
                    if vid.index < new_elem_threshold {
                        // quick check to see if this variable was
                        // created since the snapshot started or not.
                        let escaping_type = self.probe(vid).unwrap();
                        escaping_types.push(escaping_type);
                    }
                    debug!("SpecifyVar({:?}) new_elem_threshold={}", vid, new_elem_threshold);
                }

                _ => { }
            }
        }

        escaping_types
    }

    pub fn unsolved_variables(&self) -> Vec<ty::TyVid> {
        self.values
            .iter()
            .enumerate()
            .filter_map(|(i, value)| match &value.value {
                &TypeVariableValue::Known(_) => None,
                &TypeVariableValue::Bounded { .. } => Some(ty::TyVid { index: i as u32 })
            })
            .collect()
    }
}

impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
    type Value = TypeVariableData<'tcx>;
    type Undo = UndoEntry<'tcx>;

    fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: UndoEntry<'tcx>) {
        match action {
            SpecifyVar(vid, relations, default) => {
                values[vid.index as usize].value = Bounded {
                    relations: relations,
                    default: default
                };
            }

            Relate(a, b) => {
                relations(&mut (*values)[a.index as usize]).pop();
                relations(&mut (*values)[b.index as usize]).pop();
            }
        }
    }
}

fn relations<'a>(v: &'a mut TypeVariableData) -> &'a mut Vec<Relation> {
    match v.value {
        Known(_) => panic!("var_sub_var: variable is known"),
        Bounded { ref mut relations, .. } => relations
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 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.

//! A pass that removes various redundancies in the CFG. It should be
//! called after every significant CFG modification to tidy things
//! up.
//!
//! This pass must also be run before any analysis passes because it removes
//! dead blocks, and some of these can be ill-typed.
//!
//! The cause of that is that typeck lets most blocks whose end is not
//! reachable have an arbitrary return type, rather than having the
//! usual () return type (as a note, typeck's notion of reachability
//! is in fact slightly weaker than MIR CFG reachability - see #31617).
//!
//! A standard example of the situation is:
//! ```rust
//!   fn example() {
//!       let _a: char = { return; };
//!   }
//! ```
//!
//! Here the block (`{ return; }`) has the return type `char`,
//! rather than `()`, but the MIR we naively generate still contains
//! the `_a = ()` write in the unreachable block "after" the return.

use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc::ty::TyCtxt;
use rustc::mir::repr::*;
use rustc::mir::transform::{MirPass, MirSource, Pass};
use rustc::mir::traversal;
use std::fmt;

pub struct SimplifyCfg<'a> { label: &'a str }

impl<'a> SimplifyCfg<'a> {
    pub fn new(label: &'a str) -> Self {
        SimplifyCfg { label: label }
    }
}

impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
    fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
        CfgSimplifier::new(mir).simplify();
        remove_dead_blocks(mir);

        // FIXME: Should probably be moved into some kind of pass manager
        mir.basic_blocks_mut().raw.shrink_to_fit();
    }
}

impl<'l> Pass for SimplifyCfg<'l> {
    fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> {
        Some(Box::new(self.label))
    }

    // avoid calling `type_name` - it contains `<'static>`
    fn name(&self) -> ::std::borrow::Cow<'static, str> { "SimplifyCfg".into() }
}

pub struct CfgSimplifier<'a, 'tcx: 'a> {
    basic_blocks: &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
    pred_count: IndexVec<BasicBlock, u32>
}

impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
    fn new(mir: &'a mut Mir<'tcx>) -> Self {
        let mut pred_count = IndexVec::from_elem(0u32, mir.basic_blocks());

        // we can't use mir.predecessors() here because that counts
        // dead blocks, which we don't want to.
        pred_count[START_BLOCK] = 1;

        for (_, data) in traversal::preorder(mir) {
            if let Some(ref term) = data.terminator {
                for &tgt in term.successors().iter() {
                    pred_count[tgt] += 1;
                }
            }
        }

        let basic_blocks = mir.basic_blocks_mut();

        CfgSimplifier {
            basic_blocks: basic_blocks,
            pred_count: pred_count
        }
    }

    fn simplify(mut self) {
        loop {
            let mut changed = false;

            for bb in (0..self.basic_blocks.len()).map(BasicBlock::new) {
                if self.pred_count[bb] == 0 {
                    continue
                }

                debug!("simplifying {:?}", bb);

                let mut terminator = self.basic_blocks[bb].terminator.take()
                    .expect("invalid terminator state");

                for successor in terminator.successors_mut() {
                    self.collapse_goto_chain(successor, &mut changed);
                }

                let mut new_stmts = vec![];
                let mut inner_changed = true;
                while inner_changed {
                    inner_changed = false;
                    inner_changed |= self.simplify_branch(&mut terminator);
                    inner_changed |= self.merge_successor(&mut new_stmts, &mut terminator);
                    changed |= inner_changed;
                }

                self.basic_blocks[bb].statements.extend(new_stmts);
                self.basic_blocks[bb].terminator = Some(terminator);

                changed |= inner_changed;
            }

            if !changed { break }
        }
    }

    // Collapse a goto chain starting from `start`
    fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
        let mut terminator = match self.basic_blocks[*start] {
            BasicBlockData {
                ref statements,
                terminator: ref mut terminator @ Some(Terminator {
                    kind: TerminatorKind::Goto { .. }, ..
                }), ..
            } if statements.is_empty() => terminator.take(),
            // if `terminator` is None, this means we are in a loop. In that
            // case, let all the loop collapse to its entry.
            _ => return
        };

        let target = match terminator {
            Some(Terminator { kind: TerminatorKind::Goto { ref mut target }, .. }) => {
                self.collapse_goto_chain(target, changed);
                *target
            }
            _ => unreachable!()
        };
        self.basic_blocks[*start].terminator = terminator;

        debug!("collapsing goto chain from {:?} to {:?}", *start, target);

        *changed |= *start != target;
        self.pred_count[target] += 1;
        self.pred_count[*start] -= 1;
        *start = target;
    }

    // merge a block with 1 `goto` predecessor to its parent
    fn merge_successor(&mut self,
                       new_stmts: &mut Vec<Statement<'tcx>>,
                       terminator: &mut Terminator<'tcx>)
                       -> bool
    {
        let target = match terminator.kind {
            TerminatorKind::Goto { target }
                if self.pred_count[target] == 1
                => target,
            _ => return false
        };

        debug!("merging block {:?} into {:?}", target, terminator);
        *terminator = match self.basic_blocks[target].terminator.take() {
            Some(terminator) => terminator,
            None => {
                // unreachable loop - this should not be possible, as we
                // don't strand blocks, but handle it correctly.
                return false
            }
        };
        new_stmts.extend(self.basic_blocks[target].statements.drain(..));
        self.pred_count[target] = 0;

        true
    }

    // turn a branch with all successors identical to a goto
    fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
        match terminator.kind {
            TerminatorKind::If { .. } |
            TerminatorKind::Switch { .. } |
            TerminatorKind::SwitchInt { .. } => {},
            _ => return false
        };

        let first_succ = {
            let successors = terminator.successors();
            if let Some(&first_succ) = terminator.successors().get(0) {
                if successors.iter().all(|s| *s == first_succ) {
                    self.pred_count[first_succ] -= (successors.len()-1) as u32;
                    first_succ
                } else {
                    return false
                }
            } else {
                return false
            }
        };

        debug!("simplifying branch {:?}", terminator);
        terminator.kind = TerminatorKind::Goto { target: first_succ };
        true
    }
}

fn remove_dead_blocks(mir: &mut Mir) {
    let mut seen = BitVector::new(mir.basic_blocks().len());
    for (bb, _) in traversal::preorder(mir) {
        seen.insert(bb.index());
    }

    let basic_blocks = mir.basic_blocks_mut();

    let num_blocks = basic_blocks.len();
    let mut replacements : Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
    let mut used_blocks = 0;
    for alive_index in seen.iter() {
        replacements[alive_index] = BasicBlock::new(used_blocks);
        if alive_index != used_blocks {
            // Swap the next alive block data with the current available slot. Since alive_index is
            // non-decreasing this is a valid operation.
            basic_blocks.raw.swap(alive_index, used_blocks);
        }
        used_blocks += 1;
    }
    basic_blocks.raw.truncate(used_blocks);

    for block in basic_blocks {
        for target in block.terminator_mut().successors_mut() {
            *target = replacements[target.index()];
        }
    }
}
<commit_msg>SimplifyCfg: don't incref target when collapsing a goto with 1 pred<commit_after>// Copyright 2015 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.

//! A pass that removes various redundancies in the CFG. It should be
//! called after every significant CFG modification to tidy things
//! up.
//!
//! This pass must also be run before any analysis passes because it removes
//! dead blocks, and some of these can be ill-typed.
//!
//! The cause of that is that typeck lets most blocks whose end is not
//! reachable have an arbitrary return type, rather than having the
//! usual () return type (as a note, typeck's notion of reachability
//! is in fact slightly weaker than MIR CFG reachability - see #31617).
//!
//! A standard example of the situation is:
//! ```rust
//!   fn example() {
//!       let _a: char = { return; };
//!   }
//! ```
//!
//! Here the block (`{ return; }`) has the return type `char`,
//! rather than `()`, but the MIR we naively generate still contains
//! the `_a = ()` write in the unreachable block "after" the return.

use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc::ty::TyCtxt;
use rustc::mir::repr::*;
use rustc::mir::transform::{MirPass, MirSource, Pass};
use rustc::mir::traversal;
use std::fmt;

pub struct SimplifyCfg<'a> { label: &'a str }

impl<'a> SimplifyCfg<'a> {
    pub fn new(label: &'a str) -> Self {
        SimplifyCfg { label: label }
    }
}

impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
    fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &mut Mir<'tcx>) {
        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
        CfgSimplifier::new(mir).simplify();
        remove_dead_blocks(mir);

        // FIXME: Should probably be moved into some kind of pass manager
        mir.basic_blocks_mut().raw.shrink_to_fit();
    }
}

impl<'l> Pass for SimplifyCfg<'l> {
    fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> {
        Some(Box::new(self.label))
    }

    // avoid calling `type_name` - it contains `<'static>`
    fn name(&self) -> ::std::borrow::Cow<'static, str> { "SimplifyCfg".into() }
}

pub struct CfgSimplifier<'a, 'tcx: 'a> {
    basic_blocks: &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
    pred_count: IndexVec<BasicBlock, u32>
}

impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
    fn new(mir: &'a mut Mir<'tcx>) -> Self {
        let mut pred_count = IndexVec::from_elem(0u32, mir.basic_blocks());

        // we can't use mir.predecessors() here because that counts
        // dead blocks, which we don't want to.
        pred_count[START_BLOCK] = 1;

        for (_, data) in traversal::preorder(mir) {
            if let Some(ref term) = data.terminator {
                for &tgt in term.successors().iter() {
                    pred_count[tgt] += 1;
                }
            }
        }

        let basic_blocks = mir.basic_blocks_mut();

        CfgSimplifier {
            basic_blocks: basic_blocks,
            pred_count: pred_count
        }
    }

    fn simplify(mut self) {
        loop {
            let mut changed = false;

            for bb in (0..self.basic_blocks.len()).map(BasicBlock::new) {
                if self.pred_count[bb] == 0 {
                    continue
                }

                debug!("simplifying {:?}", bb);

                let mut terminator = self.basic_blocks[bb].terminator.take()
                    .expect("invalid terminator state");

                for successor in terminator.successors_mut() {
                    self.collapse_goto_chain(successor, &mut changed);
                }

                let mut new_stmts = vec![];
                let mut inner_changed = true;
                while inner_changed {
                    inner_changed = false;
                    inner_changed |= self.simplify_branch(&mut terminator);
                    inner_changed |= self.merge_successor(&mut new_stmts, &mut terminator);
                    changed |= inner_changed;
                }

                self.basic_blocks[bb].statements.extend(new_stmts);
                self.basic_blocks[bb].terminator = Some(terminator);

                changed |= inner_changed;
            }

            if !changed { break }
        }
    }

    // Collapse a goto chain starting from `start`
    fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
        let mut terminator = match self.basic_blocks[*start] {
            BasicBlockData {
                ref statements,
                terminator: ref mut terminator @ Some(Terminator {
                    kind: TerminatorKind::Goto { .. }, ..
                }), ..
            } if statements.is_empty() => terminator.take(),
            // if `terminator` is None, this means we are in a loop. In that
            // case, let all the loop collapse to its entry.
            _ => return
        };

        let target = match terminator {
            Some(Terminator { kind: TerminatorKind::Goto { ref mut target }, .. }) => {
                self.collapse_goto_chain(target, changed);
                *target
            }
            _ => unreachable!()
        };
        self.basic_blocks[*start].terminator = terminator;

        debug!("collapsing goto chain from {:?} to {:?}", *start, target);

        *changed |= *start != target;

        if self.pred_count[*start] == 1 {
            // This is the last reference to *start, so the pred-count to
            // to target is moved into the current block.
            self.pred_count[*start] = 0;
        } else {
            self.pred_count[target] += 1;
            self.pred_count[*start] -= 1;
        }

        *start = target;
    }

    // merge a block with 1 `goto` predecessor to its parent
    fn merge_successor(&mut self,
                       new_stmts: &mut Vec<Statement<'tcx>>,
                       terminator: &mut Terminator<'tcx>)
                       -> bool
    {
        let target = match terminator.kind {
            TerminatorKind::Goto { target }
                if self.pred_count[target] == 1
                => target,
            _ => return false
        };

        debug!("merging block {:?} into {:?}", target, terminator);
        *terminator = match self.basic_blocks[target].terminator.take() {
            Some(terminator) => terminator,
            None => {
                // unreachable loop - this should not be possible, as we
                // don't strand blocks, but handle it correctly.
                return false
            }
        };
        new_stmts.extend(self.basic_blocks[target].statements.drain(..));
        self.pred_count[target] = 0;

        true
    }

    // turn a branch with all successors identical to a goto
    fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
        match terminator.kind {
            TerminatorKind::If { .. } |
            TerminatorKind::Switch { .. } |
            TerminatorKind::SwitchInt { .. } => {},
            _ => return false
        };

        let first_succ = {
            let successors = terminator.successors();
            if let Some(&first_succ) = terminator.successors().get(0) {
                if successors.iter().all(|s| *s == first_succ) {
                    self.pred_count[first_succ] -= (successors.len()-1) as u32;
                    first_succ
                } else {
                    return false
                }
            } else {
                return false
            }
        };

        debug!("simplifying branch {:?}", terminator);
        terminator.kind = TerminatorKind::Goto { target: first_succ };
        true
    }
}

fn remove_dead_blocks(mir: &mut Mir) {
    let mut seen = BitVector::new(mir.basic_blocks().len());
    for (bb, _) in traversal::preorder(mir) {
        seen.insert(bb.index());
    }

    let basic_blocks = mir.basic_blocks_mut();

    let num_blocks = basic_blocks.len();
    let mut replacements : Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
    let mut used_blocks = 0;
    for alive_index in seen.iter() {
        replacements[alive_index] = BasicBlock::new(used_blocks);
        if alive_index != used_blocks {
            // Swap the next alive block data with the current available slot. Since alive_index is
            // non-decreasing this is a valid operation.
            basic_blocks.raw.swap(alive_index, used_blocks);
        }
        used_blocks += 1;
    }
    basic_blocks.raw.truncate(used_blocks);

    for block in basic_blocks {
        for target in block.terminator_mut().successors_mut() {
            *target = replacements[target.index()];
        }
    }
}
<|endoftext|>