<commit_before>#![allow(dead_code)]

use parse::lexer::*;
use parse::tokens::*;
use ast::{Stmt, Expr, Block, TType, Local, Decl};
use ast::Stmt::*;
use ast::Expr::*;
use ast::TType::*;
use ast::Decl::*;
//use ast::*;
use ptr::{B};
//use ast::{Expr, Stmt};

type BlockStack = Vec<Block>;

pub struct Parser{
    lexer : Lexer,
    block_stack : BlockStack,
    paren_stack : Vec<char>,
    seq_expr_list : Vec<B<Expr>>
}

impl Parser{
    pub fn new(src : String)->Self{
        Parser {lexer : Lexer::new(src),
                block_stack : BlockStack::new(),
                paren_stack : Vec::new(),
                seq_expr_list : Vec::new() }
    }

    pub fn run(& mut self)->Option<Block>{
        self.parse_block()
        //self.block.generate();
    }

    fn parse_block(& mut self)->Option<Block>{
        //let mut b = Block::new();
        //self.block_stack.push(b);
        self.lexer.get_char();
        self.program(); //begin parsing
        debug_assert!(self.block_stack.len() == 1, "Only parent block should be on
                                                    the stack when the parsing is finished");
        let mut main_block = self.block_stack.pop().unwrap();
        //main_block.generate();
        //if main_block.statements.len() == 0{
        if !main_block.expr.is_some(){
            None
        }
        else{
            Some(main_block)
        }
    }

    fn program(&mut self){
      loop{
        match self.lexer.get_token(){
            //FIXME semicolon handling should change:
            Token::SemiColon => continue,
            Token::Nil |
            Token::Number |
            Token::LeftParen |
            Token::Minus |
            Token::If |
            Token::While |
            Token::For |
            Token::Break |
            Token::Let |
            Token::Ident => {
                let expr = self.expr();
                self.block_stack.last_mut().unwrap().expr = expr;
                //FIXME should we break?
                break;
            },
            /*Token::Break => {
                let mut curr_block = self.block_stack.last_mut().unwrap();
                curr_block.statements.push(Self::mk_break_stmt());
            },*/
            /*Token::Do => {
                debug_assert!(self.block_stack.len() > 0, "No parent block on the stack");
                self.block_stack.push(Block::new());
                self.expr();
                if self.lexer.curr_token == Token::End{
                    //TODO make sure we track all block openings
                    let block = self.block_stack.pop().unwrap();
                    let mut curr_block = self.block_stack.last_mut().unwrap();
                    //curr_block.statements.push(Self::mk_block_stmt(block));
                }
            },*/
            Token::Eof => {return},
            Token::End => {
                //TODO block stack pop
                return
                //continue;
            },
            _ => {panic!("Invalid token");}
        }
      }
    }

    // fn mk_var_decl(local : Local)->B<Stmt>{
    //     B(VarDeclStmt(local))
    // }
    //
    // fn mk_label_stmt(label : String)->B<Stmt>{
    //     B(ExprStmt(Self::mk_label_expr(label)))
    // }
    //
    // fn mk_label_expr(label: String)->B<Expr>{
    //     B(LabelExpr(label))
    // }
    //
    // fn mk_goto_stmt(label : String) -> B<Stmt>{
    //     B(ExprStmt(Self::mk_goto_expr(label)))
    // }
    //
    // fn mk_goto_expr(label : String) -> B<Expr>{
    //     B(GotoExpr(label))
    // }
    //
    // fn mk_break_stmt() -> B<Stmt>{
    //     B(ExprStmt(B(BreakExpr)))
    // }
    //
    // fn mk_block_stmt(block : Block) -> B<Stmt>{
    //     B(Stmt::ExprStmt(Self::mk_block_expr(block)))
    // }
    //
    // fn mk_block_expr(block : Block) -> B<Expr>{
    //     B(Expr::BlockExpr(B(block)))
    // }
    //
    // fn exprlist(&mut self){
    //      self.expr();
    //      match self.lexer.get_token(){
    //         Token::Ident => {},
    //         _ => {}
    //      }
    // }
    //
    // fn varlist(&mut self){
    //
    // }

    fn expr(&mut self) -> Option<B<Expr>> {
        match self.lexer.curr_token{
            Token::Nil => {Some(B(NilExpr))},
            Token::Number => {
                Some(B(NumExpr(self.lexer.curr_string.clone().parse::<i32>().unwrap())))
            },
            Token::Ident => {
                //check if symbol defined in the sym tab
                //if self.block_stack.last().unwrap().contains(self.lexer.curr_string)
                match self.lexer.get_token(){
                    Token::LeftSquare => {}, //subscript
                    Token::Dot => {}, //fieldexp
                    Token::LeftParen => {}, //callexpr

                    _ => {
                        return Some(B(IdExpr(self.lexer.curr_string.clone())))
                    }
                }
                Some(B(IdentExpr(self.lexer.curr_string.clone())))
            },
            Token::Let => {
                let mut b = Block::new();
                //set parent-child relationship
                self.block_stack.push(b);
                let mut decls = Vec::new();
                loop{
                    match self.lexer.get_token() {
                        Token::Type => { //typedec
                            match self.lexer.get_token() {
                                Token::Ident => {
                                    let id = self.lexer.curr_string.clone();
                                    match self.lexer.get_token(){
                                        Token::Equals => {
                                            match self.lexer.get_token(){
                                                Token::Int => decls.push(TyDec(id, TInt32)),
                                                Token::TokString => decls.push(TyDec(id, TString)),
                                                Token::Ident => decls.push(TyDec(id, TCustom(self.lexer.curr_string.clone()))),
                                                Token::Array => {
                                                    match self.lexer.get_token() {
                                                        Token::Of => {
                                                            match self.lexer.get_token() {
                                                                Token::Int => {},
                                                                Token::TokString => {},
                                                                Token::Ident => {},
                                                                _ => panic!("Expected either int, string or type-id")
                                                            }
                                                        },
                                                        _ => panic!("Expected 'of' after 'array'")
                                                    }
                                                },
                                                Token::LeftCurly => { //rectype

                                                },
                                                _ => panic!("Expected either int, string, type-id, array of, '{' after '='")
                                            }
                                        },
                                        _ => panic!("Expected '=' after type-id")
                                    }
                                },
                                _ => panic!("Expected identifier after 'type'")
                            }
                        },
                        Token::Var => { //Vardec
                            match self.lexer.get_token() {
                                Token::Ident => {
                                    let id = self.lexer.curr_string.clone();
                                    match self.lexer.get_token() {
                                        Token::Colon => {
                                            match self.lexer.get_token() {
                                                Token::Int => {
                                                    match self.lexer.get_token(){
                                                        Token::ColonEquals => {
                                                            //get rhs expr and its type
                                                            let (ty, expr) = self.evaluable_expr();
                                                            self.block_stack.last_mut().unwrap().sym_tab.borrow_mut().insert(id.clone(), ty);
                                                            decls.push(VarDec(id.clone(), TInt32, expr));
                                                        },
                                                        _ => panic!("Expected ':='")
                                                    }
                                                },
                                                Token::TokString => {
                                                    match self.lexer.get_token(){
                                                        Token::ColonEquals => {
                                                            self.expr();
                                                        },
                                                        _ => panic!("Expected ':='")
                                                    }
                                                },
                                                _ => panic!("expr : pattern not covered")
                                            }
                                        },
                                        _ => panic!("Expected ':' after identifier")
                                    }
                                },
                                _ => panic!("Expected an identifier")
                            }
                        },
                        Token::Function => { //functiondec

                        },
                        Token::In => break,
                        //FIXME Eof occurrence is an error
                        Token::Eof => break,
                        //FIXME End occurrence is an error
                        Token::End => break,
                        _ => panic!("Unexpected token. Expected a declaration or 'in'")
                    }
                }//let loop ends
                //FIXME start scanning expressions after 'in'
                return Some(B(LetExpr(decls, None)))
            },
            Token::LeftParen => { //seqexpr
                self.paren_stack.push('(');
                let e = self.expr();
                if e.is_some() {
                    self.seq_expr_list.push(e.unwrap());
                }
                //FIXME remove this:
                Some(B(SeqExpr(None)))
            },
            Token::RightParen => {
                if self.paren_stack.is_empty(){
                    panic!("Mismatched parenthesis");
                }
                self.paren_stack.pop();
                //TODO mem::replace self.seq_expr_list with Vec::new and assign it to SeqExpr
                Some(B(SeqExpr(None)))
            },
            _ => Some(B(IdentExpr("fsf".to_string())))
        }
    }

    fn evaluable_expr(&mut self)->(TType, B<Expr>){
        match self.lexer.get_token() {
            Token::Ident => {
                let id = self.lexer.curr_string.clone();
                match self.lexer.get_token() {
                    Token::Dot => {
                        match self.lexer.get_token() {
                            Token::Ident => {

                            },
                            _ => panic!("evaluable_expr : pattern not covered")
                        }
                    },
                    Token::LeftSquare => {

                    },
                    //FIXME can new line be replaced with a semicolon as a decl terminator instead?
                    Token::NewLine => {
                        //search the ident in the current symbol table
                        let mut b = self.block_stack.last_mut().unwrap();
                        if b.contains(&self.lexer.curr_string){
                            let m = b.sym_tab.borrow();
                            let ty = m.get(&self.lexer.curr_string).unwrap().clone();
                            return (ty.clone(), B(IdExpr(self.lexer.curr_string.clone())))
                        }
                        else{
                            panic!("Undefined symbol - {}", self.lexer.curr_string);
                        }
                    },
                    Token::Plus => {
                        return (TInt32, self.evaluable_expr().1)
                    },
                    //TODO add more binary operators
                    _ => panic!("evaluable_expr : pattern not covered")
                }
            },
            Token::Number => {
                //FIXME parse the whole numeric expression
                let num = self.lexer.curr_string.parse::<i32>().unwrap();
                let op1 = B(NumExpr(num));
                match self.lexer.get_token(){
                    Token::Plus => {
                        let (t, op2) = self.evaluable_expr();
                        //FIXME it's better to use a type-checker
                        if t == TInt32{
                            return (TInt32, B(AddExpr(op1, op2)))
                        }
                        else{
                            panic!("Expected i32 as the type of rhs expression");
                        }
                    },
                    _ => return (TInt32, op1)
                }
                //return (TInt32, B(NumExpr(num)))
            },
            _ => panic!("evaluable_expr : pattern not covered")
        }
        //FIXME remove this:
        return (TInt32, B(NumExpr(1)))
    }
}

#[test]
fn test_let_var_decl_returns_block() {
    let mut p = Parser::new("let var a : int := 1 in end".to_string());
    assert_eq!(p.run().is_some(), true);
}

#[test]
fn test_let_var_decl_returns_let_expr() {
    let mut p = Parser::new("let var a : int := 1 in end".to_string());
    let b = p.run().unwrap();
    match *b.expr.unwrap(){
        LetExpr(ref v, ref o) => {
            assert_eq!(v.len(), 1);
            assert_eq!(o.is_some(), false);
            match v[0]{
                VarDec(ref id, ref ty, ref e) => {
                    assert_eq!(*id, "a".to_string());
                    match **e{ //**e means deref deref B<T> which results in T
                        NumExpr(ref n) => assert_eq!(1, *n),
                        _ => {}
                    }
                },
                _ => {}
            }
        },
        _ => {}
    }
}

#[test]
fn test_let_var_decl_sym_tab_count() {
    let mut p = Parser::new("let var a : int := 1 in end".to_string());
    let b = p.run().unwrap();
    assert_eq!(b.sym_tab.borrow().len(), 1);
    assert_eq!(b.sym_tab.borrow().get(&"a".to_string()), Some(&TInt32));
}

#[test]
fn test_let_add_expr() {
    let mut p = Parser::new("let var a : int := 1 + 3 + 1 in end".to_string());
    let b = p.run().unwrap();
    match *b.expr.unwrap(){
        LetExpr(ref v, ref o) => {
            assert_eq!(v.len(), 1);
            assert_eq!(o.is_some(), false);
            match v[0]{
                VarDec(ref id, ref ty, ref e) => {
                    assert_eq!(*id, "a".to_string());
                    match **e{ //**e means deref deref B<T> which results in T
                        AddExpr(ref e1, ref e2) => {
                            match **e1{
                                NumExpr(ref n) => assert_eq!(*n, 1),
                                _ => panic!("num expr expected")
                            }

                            match **e2{
                                AddExpr(ref e1, ref e2) => {
                                    match **e1{
                                        NumExpr(ref n) => assert_eq!(*n, 3),
                                        _ => panic!("num expr expected")
                                    }

                                    match **e2{
                                        NumExpr(ref n) => assert_eq!(*n, 1),
                                        _ => panic!("num expr expected")
                                    }
                                },
                                _ => panic!("add expr expected")
                            }
                        },
                        _ => panic!("add expr expected")
                    }
                },
                _ => panic!("ver decl expected")
            }
        },
        _ => panic!("let expr expected")
    }
}

#[test]
fn test_parse_2_vars_in_let() {
    let mut p = Parser::new("let var a : int := 1\nvar b : int:=2\n in end".to_string());
    let b = p.run().unwrap();
    match *b.expr.unwrap(){
        LetExpr(ref v, ref o) => {
            assert_eq!(v.len(), 2);
        },
        _ => {}
    }
}
<commit_msg>refactoring expr parsing into seperate methods<commit_after>#![allow(dead_code)]

use parse::lexer::*;
use parse::tokens::*;
use ast::{Stmt, Expr, Block, TType, Local, Decl};
use ast::Stmt::*;
use ast::Expr::*;
use ast::TType::*;
use ast::Decl::*;
//use ast::*;
use ptr::{B};
//use ast::{Expr, Stmt};

type BlockStack = Vec<Block>;

pub struct Parser{
    lexer : Lexer,
    block_stack : BlockStack,
    paren_stack : Vec<char>,
    seq_expr_list : Vec<B<Expr>>
}

impl Parser{
    pub fn new(src : String)->Self{
        Parser {lexer : Lexer::new(src),
                block_stack : BlockStack::new(),
                paren_stack : Vec::new(),
                seq_expr_list : Vec::new() }
    }

    pub fn run(& mut self)->Option<Block>{
        self.parse_block()
        //self.block.generate();
    }

    fn parse_block(& mut self)->Option<Block>{
        //let mut b = Block::new();
        //self.block_stack.push(b);
        self.lexer.get_char();
        self.program(); //begin parsing
        debug_assert!(self.block_stack.len() == 1, "Only parent block should be on
                                                    the stack when the parsing is finished");
        let mut main_block = self.block_stack.pop().unwrap();
        //main_block.generate();
        //if main_block.statements.len() == 0{
        if !main_block.expr.is_some(){
            None
        }
        else{
            Some(main_block)
        }
    }

    fn program(&mut self){
      loop{
        match self.lexer.get_token(){
            //FIXME semicolon handling should change:
            Token::SemiColon => continue,
            Token::Nil |
            Token::Number |
            Token::LeftParen |
            Token::Minus |
            Token::If |
            Token::While |
            Token::For |
            Token::Break |
            Token::Let |
            Token::Ident => {
                let expr = self.expr();
                self.block_stack.last_mut().unwrap().expr = expr;
                //FIXME should we break?
                break;
            },
            /*Token::Break => {
                let mut curr_block = self.block_stack.last_mut().unwrap();
                curr_block.statements.push(Self::mk_break_stmt());
            },*/
            /*Token::Do => {
                debug_assert!(self.block_stack.len() > 0, "No parent block on the stack");
                self.block_stack.push(Block::new());
                self.expr();
                if self.lexer.curr_token == Token::End{
                    //TODO make sure we track all block openings
                    let block = self.block_stack.pop().unwrap();
                    let mut curr_block = self.block_stack.last_mut().unwrap();
                    //curr_block.statements.push(Self::mk_block_stmt(block));
                }
            },*/
            Token::Eof => {return},
            Token::End => {
                //TODO block stack pop
                return
                //continue;
            },
            _ => {panic!("Invalid token");}
        }
      }
    }

    // fn mk_var_decl(local : Local)->B<Stmt>{
    //     B(VarDeclStmt(local))
    // }
    //
    // fn mk_label_stmt(label : String)->B<Stmt>{
    //     B(ExprStmt(Self::mk_label_expr(label)))
    // }
    //
    // fn mk_label_expr(label: String)->B<Expr>{
    //     B(LabelExpr(label))
    // }
    //
    // fn mk_goto_stmt(label : String) -> B<Stmt>{
    //     B(ExprStmt(Self::mk_goto_expr(label)))
    // }
    //
    // fn mk_goto_expr(label : String) -> B<Expr>{
    //     B(GotoExpr(label))
    // }
    //
    // fn mk_break_stmt() -> B<Stmt>{
    //     B(ExprStmt(B(BreakExpr)))
    // }
    //
    // fn mk_block_stmt(block : Block) -> B<Stmt>{
    //     B(Stmt::ExprStmt(Self::mk_block_expr(block)))
    // }
    //
    // fn mk_block_expr(block : Block) -> B<Expr>{
    //     B(Expr::BlockExpr(B(block)))
    // }
    //
    // fn exprlist(&mut self){
    //      self.expr();
    //      match self.lexer.get_token(){
    //         Token::Ident => {},
    //         _ => {}
    //      }
    // }
    //
    // fn varlist(&mut self){
    //
    // }

    fn expr(&mut self) -> Option<B<Expr>> {
        match self.lexer.curr_token{
            Token::Nil => {Some(B(NilExpr))},
            Token::Number => {
                Some(B(NumExpr(self.lexer.curr_string.clone().parse::<i32>().unwrap())))
            },
            Token::Ident => {
                return self.parse_ident_expr()
            },
            Token::Let =>{
                return self.parse_let_expr()
            }
            Token::LeftParen => { //seqexpr
                self.paren_stack.push('(');
                let e = self.expr();
                if e.is_some() {
                    self.seq_expr_list.push(e.unwrap());
                }
                //FIXME remove this:
                Some(B(SeqExpr(None)))
            },
            Token::RightParen => {
                if self.paren_stack.is_empty(){
                    panic!("Mismatched parenthesis");
                }
                self.paren_stack.pop();
                //TODO mem::replace self.seq_expr_list with Vec::new and assign it to SeqExpr
                Some(B(SeqExpr(None)))
            },
            _ => Some(B(IdentExpr("fsf".to_string())))
        }
    }

    fn evaluable_expr(&mut self)->(TType, B<Expr>){
        match self.lexer.get_token() {
            Token::Ident => {
                let id = self.lexer.curr_string.clone();
                match self.lexer.get_token() {
                    Token::Dot => {
                        match self.lexer.get_token() {
                            Token::Ident => {

                            },
                            _ => panic!("evaluable_expr : pattern not covered")
                        }
                    },
                    Token::LeftSquare => {

                    },
                    //FIXME can new line be replaced with a semicolon as a decl terminator instead?
                    Token::NewLine => {
                        //search the ident in the current symbol table
                        let mut b = self.block_stack.last_mut().unwrap();
                        if b.contains(&self.lexer.curr_string){
                            let m = b.sym_tab.borrow();
                            let ty = m.get(&self.lexer.curr_string).unwrap().clone();
                            return (ty.clone(), B(IdExpr(self.lexer.curr_string.clone())))
                        }
                        else{
                            panic!("Undefined symbol - {}", self.lexer.curr_string);
                        }
                    },
                    Token::Plus => {
                        return (TInt32, self.evaluable_expr().1)
                    },
                    //TODO add more binary operators
                    _ => panic!("evaluable_expr : pattern not covered")
                }
            },
            Token::Number => {
                //FIXME parse the whole numeric expression
                let num = self.lexer.curr_string.parse::<i32>().unwrap();
                let op1 = B(NumExpr(num));
                match self.lexer.get_token(){
                    Token::Plus => {
                        let (t, op2) = self.evaluable_expr();
                        //FIXME it's better to use a type-checker
                        if t == TInt32{
                            return (TInt32, B(AddExpr(op1, op2)))
                        }
                        else{
                            panic!("Expected i32 as the type of rhs expression");
                        }
                    },
                    _ => return (TInt32, op1)
                }
                //return (TInt32, B(NumExpr(num)))
            },
            _ => panic!("evaluable_expr : pattern not covered")
        }
        //FIXME remove this:
        return (TInt32, B(NumExpr(1)))
    }

    fn parse_let_expr(&mut self) -> Option<B<Expr>>{
        let mut b = Block::new();
        //set parent-child relationship
        self.block_stack.push(b);
        let mut decls : Vec<Decl> = Vec::new();
        loop{
            match self.lexer.get_token() {
                Token::Type => { //typedec
                    self.parse_type_decl(&mut decls);
                },
                Token::Var => { //Vardec
                    self.parse_var_decl(&mut decls);
                },
                Token::Function => { //functiondec

                },
                Token::In => break,
                //FIXME Eof occurrence is an error
                Token::Eof => break,
                //FIXME End occurrence is an error
                Token::End => break,
                _ => panic!("Unexpected token. Expected a declaration or 'in'")
            }
        }//let loop ends
        if self.lexer.curr_token == Token::In{
            //FIXME get the list of exprs and the type of the last expr in the list
        }
        else{
            panic!("Expected 'in' after declarations");
        }
        return Some(B(LetExpr(decls, None)))
    }

    fn parse_type_decl(&mut self, decls : &mut Vec<Decl>){
        match self.lexer.get_token() {
            Token::Ident => {
                let id = self.lexer.curr_string.clone();
                match self.lexer.get_token(){
                    Token::Equals => {
                        match self.lexer.get_token(){
                            Token::Int => decls.push(TyDec(id, TInt32)),
                            Token::TokString => decls.push(TyDec(id, TString)),
                            Token::Ident => decls.push(TyDec(id, TCustom(self.lexer.curr_string.clone()))),
                            Token::Array => {
                                match self.lexer.get_token() {
                                    Token::Of => {
                                        match self.lexer.get_token() {
                                            Token::Int => {},
                                            Token::TokString => {},
                                            Token::Ident => {},
                                            _ => panic!("Expected either int, string or type-id")
                                        }
                                    },
                                    _ => panic!("Expected 'of' after 'array'")
                                }
                            },
                            Token::LeftCurly => { //rectype

                            },
                            _ => panic!("Expected either int, string, type-id, array of, '{' after '='")
                        }
                    },
                    _ => panic!("Expected '=' after type-id")
                }
            },
            _ => panic!("Expected identifier after 'type'")
        }
    }

    fn parse_var_decl(&mut self,  decls : &mut Vec<Decl>){
        match self.lexer.get_token() {
            Token::Ident => {
                let id = self.lexer.curr_string.clone();
                match self.lexer.get_token() {
                    Token::Colon => {
                        match self.lexer.get_token() {
                            Token::Int => {
                                match self.lexer.get_token(){
                                    Token::ColonEquals => {
                                        //get rhs expr and its type
                                        let (ty, expr) = self.evaluable_expr();
                                        self.block_stack.last_mut().unwrap().sym_tab.borrow_mut().insert(id.clone(), ty);
                                        decls.push(VarDec(id.clone(), TInt32, expr));
                                    },
                                    _ => panic!("Expected ':='")
                                }
                            },
                            Token::TokString => {
                                match self.lexer.get_token(){
                                    Token::ColonEquals => {
                                        self.expr();
                                    },
                                    _ => panic!("Expected ':='")
                                }
                            },
                            _ => panic!("expr : pattern not covered")
                        }
                    },
                    _ => panic!("Expected ':' after identifier")
                }
            },
            _ => panic!("Expected an identifier")
        }
    }

    fn parse_ident_expr(&mut self) -> Option<B<Expr>>{
        //check if symbol defined in the sym tab
        //if self.block_stack.last().unwrap().contains(self.lexer.curr_string)
        match self.lexer.get_token(){
            Token::LeftSquare => {}, //subscript
            Token::Dot => {}, //fieldexp
            Token::LeftParen => {}, //callexpr

            _ => {
                return Some(B(IdExpr(self.lexer.curr_string.clone())))
            }
        }
        Some(B(IdentExpr(self.lexer.curr_string.clone())))
    }
}

#[test]
fn test_let_var_decl_returns_block() {
    let mut p = Parser::new("let var a : int := 1 in end".to_string());
    assert_eq!(p.run().is_some(), true);
}

#[test]
fn test_let_var_decl_returns_let_expr() {
    let mut p = Parser::new("let var a : int := 1 in end".to_string());
    let b = p.run().unwrap();
    match *b.expr.unwrap(){
        LetExpr(ref v, ref o) => {
            assert_eq!(v.len(), 1);
            assert_eq!(o.is_some(), false);
            match v[0]{
                VarDec(ref id, ref ty, ref e) => {
                    assert_eq!(*id, "a".to_string());
                    match **e{ //**e means deref deref B<T> which results in T
                        NumExpr(ref n) => assert_eq!(1, *n),
                        _ => {}
                    }
                },
                _ => {}
            }
        },
        _ => {}
    }
}

#[test]
fn test_let_var_decl_sym_tab_count() {
    let mut p = Parser::new("let var a : int := 1 in end".to_string());
    let b = p.run().unwrap();
    assert_eq!(b.sym_tab.borrow().len(), 1);
    assert_eq!(b.sym_tab.borrow().get(&"a".to_string()), Some(&TInt32));
}

#[test]
fn test_let_add_expr() {
    let mut p = Parser::new("let var a : int := 1 + 3 + 1 in end".to_string());
    let b = p.run().unwrap();
    match *b.expr.unwrap(){
        LetExpr(ref v, ref o) => {
            assert_eq!(v.len(), 1);
            assert_eq!(o.is_some(), false);
            match v[0]{
                VarDec(ref id, ref ty, ref e) => {
                    assert_eq!(*id, "a".to_string());
                    match **e{ //**e means deref deref B<T> which results in T
                        AddExpr(ref e1, ref e2) => {
                            match **e1{
                                NumExpr(ref n) => assert_eq!(*n, 1),
                                _ => panic!("num expr expected")
                            }

                            match **e2{
                                AddExpr(ref e1, ref e2) => {
                                    match **e1{
                                        NumExpr(ref n) => assert_eq!(*n, 3),
                                        _ => panic!("num expr expected")
                                    }

                                    match **e2{
                                        NumExpr(ref n) => assert_eq!(*n, 1),
                                        _ => panic!("num expr expected")
                                    }
                                },
                                _ => panic!("add expr expected")
                            }
                        },
                        _ => panic!("add expr expected")
                    }
                },
                _ => panic!("ver decl expected")
            }
        },
        _ => panic!("let expr expected")
    }
}

#[test]
fn test_parse_2_vars_in_let() {
    let mut p = Parser::new("let var a : int := 1\nvar b : int:=2\n in end".to_string());
    let b = p.run().unwrap();
    match *b.expr.unwrap(){
        LetExpr(ref v, ref o) => {
            assert_eq!(v.len(), 2);
        },
        _ => {}
    }
}
<|endoftext|>


<commit_before>extern crate differential_dataflow;
extern crate dd_server;

use differential_dataflow::operators::CountTotal;
use dd_server::{Environment, TraceHandle};

// load ./dataflows/degr_dist/target/debug/libdegr_dist.dylib build <graph_name>

#[no_mangle]
pub fn build((dataflow, handles, probe, args): Environment) -> Result<(), String> {

    if args.len() != 1 { return Err(format!("expected one argument, instead: {:?}", args)); }

    handles
        .get_mut::<TraceHandle>(&args[0])?
        .import(dataflow)
        .as_collection(|k,v| (k.item.clone(), v.clone()))
        .map(|(src, _dst)| src as usize).count_total()
        .map(|(_src, cnt)| cnt as usize).count_total()
        .inspect(|x| println!("count: {:?}", x))
        .probe_with(probe);

    Ok(())
}<commit_msg>remove .item<commit_after>extern crate differential_dataflow;
extern crate dd_server;

use differential_dataflow::operators::CountTotal;
use dd_server::{Environment, TraceHandle};

// load ./dataflows/degr_dist/target/debug/libdegr_dist.dylib build <graph_name>

#[no_mangle]
pub fn build((dataflow, handles, probe, args): Environment) -> Result<(), String> {

    if args.len() != 1 { return Err(format!("expected one argument, instead: {:?}", args)); }

    handles
        .get_mut::<TraceHandle>(&args[0])?
        .import(dataflow)
        .as_collection(|k,v| (k.clone(), v.clone()))
        .map(|(src, _dst)| src as usize).count_total()
        .map(|(_src, cnt)| cnt as usize).count_total()
        .inspect(|x| println!("count: {:?}", x))
        .probe_with(probe);

    Ok(())
}<|endoftext|>


<commit_before>//! The `Clone` trait for types that cannot be 'implicitly copied'.
//!
//! In Rust, some simple types are "implicitly copyable" and when you
//! assign them or pass them as arguments, the receiver will get a copy,
//! leaving the original value in place. These types do not require
//! allocation to copy and do not have finalizers (i.e., they do not
//! contain owned boxes or implement [`Drop`]), so the compiler considers
//! them cheap and safe to copy. For other types copies must be made
//! explicitly, by convention implementing the [`Clone`] trait and calling
//! the [`clone`] method.
//!
//! [`clone`]: Clone::clone
//!
//! Basic usage example:
//!
//! ```
//! let s = String::new(); // String type implements Clone
//! let copy = s.clone(); // so we can clone it
//! ```
//!
//! To easily implement the Clone trait, you can also use
//! `#[derive(Clone)]`. Example:
//!
//! ```
//! #[derive(Clone)] // we add the Clone trait to Morpheus struct
//! struct Morpheus {
//!    blue_pill: f32,
//!    red_pill: i64,
//! }
//!
//! fn main() {
//!    let f = Morpheus { blue_pill: 0.0, red_pill: 0 };
//!    let copy = f.clone(); // and now we can clone it!
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

/// A common trait for the ability to explicitly duplicate an object.
///
/// Differs from [`Copy`] in that [`Copy`] is implicit and extremely inexpensive, while
/// `Clone` is always explicit and may or may not be expensive. In order to enforce
/// these characteristics, Rust does not allow you to reimplement [`Copy`], but you
/// may reimplement `Clone` and run arbitrary code.
///
/// Since `Clone` is more general than [`Copy`], you can automatically make anything
/// [`Copy`] be `Clone` as well.
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d
/// implementation of [`Clone`] calls [`clone`] on each field.
///
/// [`clone`]: Clone::clone
///
/// For a generic struct, `#[derive]` implements `Clone` conditionally by adding bound `Clone` on
/// generic parameters.
///
/// ```
/// // `derive` implements Clone for Reading<T> when T is Clone.
/// #[derive(Clone)]
/// struct Reading<T> {
///     frequency: T,
/// }
/// ```
///
/// ## How can I implement `Clone`?
///
/// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally:
/// if `T: Copy`, `x: T`, and `y: &T`, then `let x = y.clone();` is equivalent to `let x = *y;`.
/// Manual implementations should be careful to uphold this invariant; however, unsafe code
/// must not rely on it to ensure memory safety.
///
/// An example is a generic struct holding a function pointer. In this case, the
/// implementation of `Clone` cannot be `derive`d, but can be implemented as:
///
/// ```
/// struct Generate<T>(fn() -> T);
///
/// impl<T> Copy for Generate<T> {}
///
/// impl<T> Clone for Generate<T> {
///     fn clone(&self) -> Self {
///         *self
///     }
/// }
/// ```
///
/// ## Additional implementors
///
/// In addition to the [implementors listed below][impls],
/// the following types also implement `Clone`:
///
/// * Function item types (i.e., the distinct types defined for each function)
/// * Function pointer types (e.g., `fn() -> i32`)
/// * Array types, for all sizes, if the item type also implements `Clone` (e.g., `[i32; 123456]`)
/// * Tuple types, if each component also implements `Clone` (e.g., `()`, `(i32, bool)`)
/// * Closure types, if they capture no value from the environment
///   or if all such captured values implement `Clone` themselves.
///   Note that variables captured by shared reference always implement `Clone`
///   (even if the referent doesn't),
///   while variables captured by mutable reference never implement `Clone`.
///
/// [impls]: #implementors
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "clone"]
#[rustc_diagnostic_item = "Clone"]
pub trait Clone: Sized {
    /// Returns a copy of the value.
    ///
    /// # Examples
    ///
    /// ```
    /// # #![allow(noop_method_call)]
    /// let hello = "Hello"; // &str implements Clone
    ///
    /// assert_eq!("Hello", hello.clone());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[must_use = "cloning is often expensive and is not expected to have side effects"]
    fn clone(&self) -> Self;

    /// Performs copy-assignment from `source`.
    ///
    /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
    /// but can be overridden to reuse the resources of `a` to avoid unnecessary
    /// allocations.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone_from(&mut self, source: &Self) {
        *self = source.clone()
    }
}

/// Derive macro generating an impl of the trait `Clone`.
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
pub macro Clone($item:item) {
    /* compiler built-in */
}

// FIXME(aburka): these structs are used solely by #[derive] to
// assert that every component of a type implements Clone or Copy.
//
// These structs should never appear in user code.
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(
    feature = "derive_clone_copy",
    reason = "deriving hack, should not be public",
    issue = "none"
)]
pub struct AssertParamIsClone<T: Clone + ?Sized> {
    _field: crate::marker::PhantomData<T>,
}
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(
    feature = "derive_clone_copy",
    reason = "deriving hack, should not be public",
    issue = "none"
)]
pub struct AssertParamIsCopy<T: Copy + ?Sized> {
    _field: crate::marker::PhantomData<T>,
}

/// Implementations of `Clone` for primitive types.
///
/// Implementations that cannot be described in Rust
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
/// in `rustc_trait_selection`.
mod impls {

    use super::Clone;

    macro_rules! impl_clone {
        ($($t:ty)*) => {
            $(
                #[stable(feature = "rust1", since = "1.0.0")]
                impl Clone for $t {
                    #[inline]
                    fn clone(&self) -> Self {
                        *self
                    }
                }
            )*
        }
    }

    impl_clone! {
        usize u8 u16 u32 u64 u128
        isize i8 i16 i32 i64 i128
        f32 f64
        bool char
    }

    #[unstable(feature = "never_type", issue = "35121")]
    impl Clone for ! {
        #[inline]
        fn clone(&self) -> Self {
            *self
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: ?Sized> Clone for *const T {
        #[inline]
        fn clone(&self) -> Self {
            *self
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: ?Sized> Clone for *mut T {
        #[inline]
        fn clone(&self) -> Self {
            *self
        }
    }

    /// Shared references can be cloned, but mutable references *cannot*!
    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: ?Sized> Clone for &T {
        #[inline]
        #[rustc_diagnostic_item = "noop_method_clone"]
        fn clone(&self) -> Self {
            *self
        }
    }

    /// Shared references can be cloned, but mutable references *cannot*!
    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: ?Sized> !Clone for &mut T {}
}
<commit_msg>Updates `Clone` docs for `Copy` comparison.<commit_after>//! The `Clone` trait for types that cannot be 'implicitly copied'.
//!
//! In Rust, some simple types are "implicitly copyable" and when you
//! assign them or pass them as arguments, the receiver will get a copy,
//! leaving the original value in place. These types do not require
//! allocation to copy and do not have finalizers (i.e., they do not
//! contain owned boxes or implement [`Drop`]), so the compiler considers
//! them cheap and safe to copy. For other types copies must be made
//! explicitly, by convention implementing the [`Clone`] trait and calling
//! the [`clone`] method.
//!
//! [`clone`]: Clone::clone
//!
//! Basic usage example:
//!
//! ```
//! let s = String::new(); // String type implements Clone
//! let copy = s.clone(); // so we can clone it
//! ```
//!
//! To easily implement the Clone trait, you can also use
//! `#[derive(Clone)]`. Example:
//!
//! ```
//! #[derive(Clone)] // we add the Clone trait to Morpheus struct
//! struct Morpheus {
//!    blue_pill: f32,
//!    red_pill: i64,
//! }
//!
//! fn main() {
//!    let f = Morpheus { blue_pill: 0.0, red_pill: 0 };
//!    let copy = f.clone(); // and now we can clone it!
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

/// A common trait for the ability to explicitly duplicate an object.
///
/// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while
/// `Clone` is always explicit and may or may not be expensive. In order to enforce
/// these characteristics, Rust does not allow you to reimplement [`Copy`], but you
/// may reimplement `Clone` and run arbitrary code.
///
/// Since `Clone` is more general than [`Copy`], you can automatically make anything
/// [`Copy`] be `Clone` as well.
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d
/// implementation of [`Clone`] calls [`clone`] on each field.
///
/// [`clone`]: Clone::clone
///
/// For a generic struct, `#[derive]` implements `Clone` conditionally by adding bound `Clone` on
/// generic parameters.
///
/// ```
/// // `derive` implements Clone for Reading<T> when T is Clone.
/// #[derive(Clone)]
/// struct Reading<T> {
///     frequency: T,
/// }
/// ```
///
/// ## How can I implement `Clone`?
///
/// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally:
/// if `T: Copy`, `x: T`, and `y: &T`, then `let x = y.clone();` is equivalent to `let x = *y;`.
/// Manual implementations should be careful to uphold this invariant; however, unsafe code
/// must not rely on it to ensure memory safety.
///
/// An example is a generic struct holding a function pointer. In this case, the
/// implementation of `Clone` cannot be `derive`d, but can be implemented as:
///
/// ```
/// struct Generate<T>(fn() -> T);
///
/// impl<T> Copy for Generate<T> {}
///
/// impl<T> Clone for Generate<T> {
///     fn clone(&self) -> Self {
///         *self
///     }
/// }
/// ```
///
/// ## Additional implementors
///
/// In addition to the [implementors listed below][impls],
/// the following types also implement `Clone`:
///
/// * Function item types (i.e., the distinct types defined for each function)
/// * Function pointer types (e.g., `fn() -> i32`)
/// * Array types, for all sizes, if the item type also implements `Clone` (e.g., `[i32; 123456]`)
/// * Tuple types, if each component also implements `Clone` (e.g., `()`, `(i32, bool)`)
/// * Closure types, if they capture no value from the environment
///   or if all such captured values implement `Clone` themselves.
///   Note that variables captured by shared reference always implement `Clone`
///   (even if the referent doesn't),
///   while variables captured by mutable reference never implement `Clone`.
///
/// [impls]: #implementors
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "clone"]
#[rustc_diagnostic_item = "Clone"]
pub trait Clone: Sized {
    /// Returns a copy of the value.
    ///
    /// # Examples
    ///
    /// ```
    /// # #![allow(noop_method_call)]
    /// let hello = "Hello"; // &str implements Clone
    ///
    /// assert_eq!("Hello", hello.clone());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[must_use = "cloning is often expensive and is not expected to have side effects"]
    fn clone(&self) -> Self;

    /// Performs copy-assignment from `source`.
    ///
    /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
    /// but can be overridden to reuse the resources of `a` to avoid unnecessary
    /// allocations.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone_from(&mut self, source: &Self) {
        *self = source.clone()
    }
}

/// Derive macro generating an impl of the trait `Clone`.
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
pub macro Clone($item:item) {
    /* compiler built-in */
}

// FIXME(aburka): these structs are used solely by #[derive] to
// assert that every component of a type implements Clone or Copy.
//
// These structs should never appear in user code.
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(
    feature = "derive_clone_copy",
    reason = "deriving hack, should not be public",
    issue = "none"
)]
pub struct AssertParamIsClone<T: Clone + ?Sized> {
    _field: crate::marker::PhantomData<T>,
}
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(
    feature = "derive_clone_copy",
    reason = "deriving hack, should not be public",
    issue = "none"
)]
pub struct AssertParamIsCopy<T: Copy + ?Sized> {
    _field: crate::marker::PhantomData<T>,
}

/// Implementations of `Clone` for primitive types.
///
/// Implementations that cannot be described in Rust
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
/// in `rustc_trait_selection`.
mod impls {

    use super::Clone;

    macro_rules! impl_clone {
        ($($t:ty)*) => {
            $(
                #[stable(feature = "rust1", since = "1.0.0")]
                impl Clone for $t {
                    #[inline]
                    fn clone(&self) -> Self {
                        *self
                    }
                }
            )*
        }
    }

    impl_clone! {
        usize u8 u16 u32 u64 u128
        isize i8 i16 i32 i64 i128
        f32 f64
        bool char
    }

    #[unstable(feature = "never_type", issue = "35121")]
    impl Clone for ! {
        #[inline]
        fn clone(&self) -> Self {
            *self
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: ?Sized> Clone for *const T {
        #[inline]
        fn clone(&self) -> Self {
            *self
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: ?Sized> Clone for *mut T {
        #[inline]
        fn clone(&self) -> Self {
            *self
        }
    }

    /// Shared references can be cloned, but mutable references *cannot*!
    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: ?Sized> Clone for &T {
        #[inline]
        #[rustc_diagnostic_item = "noop_method_clone"]
        fn clone(&self) -> Self {
            *self
        }
    }

    /// Shared references can be cloned, but mutable references *cannot*!
    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: ?Sized> !Clone for &mut T {}
}
<|endoftext|>


<commit_before>#![recursion_limit = "256"]
#![feature(drain_filter)]

pub mod wire;
pub mod irc_state;

use futures::stream::StreamExt;
use std::net::ToSocketAddrs;
use std::time::Duration;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
use tokio::sync::mpsc;

use futures::future::FutureExt;
use futures::select;

pub struct ServerInfo {
    /// Server address
    pub addr: String,

    /// Server port
    pub port: u16,

    /// Server password.
    pub pass: Option<String>,

    pub hostname: String,

    pub realname: String,

    /// Nicks to select when logging in.
    pub nicks: Vec<String>,

    /// Channels to automatically join
    pub auto_join: Vec<String>,

    /// Nickserv password. Sent to NickServ on connecting to the server and nick change, before
    /// join commands.
    pub nickserv_ident: Option<String>,
}

#[derive(Debug)]
pub enum IrcEv {
    Connecting,
    Connected,
    Disconnected,
    IoErr(std::io::Error),
    CantResolveAddr,
    NickChange(String),
}

#[derive(Debug)]
enum IrcCmd {
    Msg(String),
}

pub struct IrcClient {
    msg_chan: mpsc::Sender<IrcCmd>,
}

impl IrcClient {
    pub fn join(&mut self, chan: &str) {
        self.msg_chan
            .try_send(IrcCmd::Msg(format!("JOIN {}\r\n", chan)))
            .unwrap();
    }
}

#[derive(Debug)]
pub enum ConnectError {
    CantResolveAddr,
    IoError(std::io::Error),
}

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

pub async fn connect(
    server_info: ServerInfo,
) -> Result<(IrcClient, mpsc::Receiver<IrcEv>), ConnectError> {
    //
    // Create communication channels
    //

    // Channel for returning IRC events to user.
    let (mut snd_ev, rcv_ev) = mpsc::channel::<IrcEv>(100);
    // Channel for commands from user.
    let (snd_cmd, rcv_cmd) = mpsc::channel::<IrcCmd>(100);
    // Channel for the sender task. TODO: Find a way to remove this.
    let (mut snd_msg, mut rcv_msg) = mpsc::channel::<String>(100);

    //
    // Create the main loop task
    //

    tokio::spawn(async move {
        // Main loop just tries to (re)connect
        /* 'connect: */ loop {
            snd_ev.send(IrcEv::Connecting).await.unwrap();

            //
            // Resolve IP address
            //

            let serv_name = server_info.addr.clone();
            let port = server_info.port;

            println!("Resolving address");

            let mut addr_iter = match tokio_executor::blocking::run(move || {
                (serv_name.as_str(), port).to_socket_addrs()
            })
            .await
            {
                Err(io_err) => {
                    snd_ev.send(IrcEv::IoErr(io_err)).await.unwrap();
                    // Wait 30 seconds before looping
                    tokio::timer::delay(tokio::clock::now() + Duration::from_secs(30)).await;
                    continue;
                }
                Ok(addr_iter) => addr_iter,
            };

            println!("Address resolved");

            let addr = match addr_iter.next() {
                None => {
                    snd_ev.send(IrcEv::CantResolveAddr).await.unwrap();
                    break;
                }
                Some(addr) => addr,
            };

            //
            // Establish TCP connection to the server
            //

            println!("Establishing connection ...");

            let stream = match TcpStream::connect(&addr).await {
                Err(io_err) => {
                    snd_ev.send(IrcEv::IoErr(io_err)).await.unwrap();
                    // Wait 30 seconds before looping
                    tokio::timer::delay(tokio::clock::now() + Duration::from_secs(30)).await;
                    continue;
                }
                Ok(stream) => stream,
            };

            println!("Done");

            let (mut read_half, mut write_half) = stream.split();

            //
            // Do the business
            //

            // Spawn a task for outgoing messages.
            tokio::spawn(async move {
                while let Some(msg) = rcv_msg.next().await {
                    if let Err(io_err) = write_half.write_all(msg.as_str().as_bytes()).await {
                        println!("IO error when writing: {:?}", io_err);
                        return;
                    }
                }
            });

            let mut parse_buf: Vec<u8> = Vec::with_capacity(1024);
            let mut irc_state = irc_state::IrcState::new(&server_info, &mut snd_msg);

            let mut rcv_cmd_fused = rcv_cmd.fuse();

            loop {
                let mut read_buf: [u8; 1024] = [0; 1024];

                select! {
                    cmd = rcv_cmd_fused.next() => {
                        match cmd {
                            None => {
                                println!("main loop: command channel terminated from the other end");
                                // That's OK, rcv_cmd_fused will never be ready again
                            }
                            Some(IrcCmd::Msg(msg)) => {
                                // FIXME something like this
                                println!(">>> {}", &msg[..msg.len()-2]);
                            }
                        }
                    }
                    bytes = read_half.read(&mut read_buf).fuse() => {
                        match bytes {
                            Err(io_err) => {
                                println!("main loop: error when reading from socket: {:?}", io_err);
                                return;
                            }
                            Ok(bytes) => {
                                parse_buf.extend_from_slice(&read_buf[0..bytes]);
                                while let Some(msg) = wire::parse_irc_msg(&mut parse_buf) {
                                    println!("parsed msg: {:?}", msg);
                                    irc_state.update(&msg, &mut snd_ev, &mut snd_msg);
                                }
                            }
                        }
                    }
                }
            }
        }
    });

    Ok((IrcClient { msg_chan: snd_cmd }, rcv_ev))
}
<commit_msg>Implement reconnect loop<commit_after>#![recursion_limit = "256"]
#![feature(drain_filter)]

pub mod wire;
pub mod irc_state;

use futures::stream::StreamExt;
use std::net::ToSocketAddrs;
use std::time::Duration;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
use tokio::sync::mpsc;

use futures::future::FutureExt;
use futures::select;

pub struct ServerInfo {
    /// Server address
    pub addr: String,

    /// Server port
    pub port: u16,

    /// Server password.
    pub pass: Option<String>,

    pub hostname: String,

    pub realname: String,

    /// Nicks to select when logging in.
    pub nicks: Vec<String>,

    /// Channels to automatically join
    pub auto_join: Vec<String>,

    /// Nickserv password. Sent to NickServ on connecting to the server and nick change, before
    /// join commands.
    pub nickserv_ident: Option<String>,
}

#[derive(Debug)]
pub enum IrcEv {
    Connecting,
    Connected,
    Disconnected,
    IoErr(std::io::Error),
    CantResolveAddr,
    NickChange(String),
}

#[derive(Debug)]
enum IrcCmd {
    Msg(String),
}

pub struct IrcClient {
    msg_chan: mpsc::Sender<IrcCmd>,
}

impl IrcClient {
    pub fn join(&mut self, chan: &str) {
        self.msg_chan
            .try_send(IrcCmd::Msg(format!("JOIN {}\r\n", chan)))
            .unwrap();
    }
}

#[derive(Debug)]
pub enum ConnectError {
    CantResolveAddr,
    IoError(std::io::Error),
}

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

pub async fn connect(
    server_info: ServerInfo,
) -> Result<(IrcClient, mpsc::Receiver<IrcEv>), ConnectError> {
    //
    // Create communication channels
    //

    // Channel for returning IRC events to user.
    let (mut snd_ev, rcv_ev) = mpsc::channel::<IrcEv>(100);
    // Channel for commands from user.
    let (snd_cmd, rcv_cmd) = mpsc::channel::<IrcCmd>(100);
    let mut rcv_cmd_fused = rcv_cmd.fuse();

    //
    // Create the main loop task
    //

    tokio::spawn(async move {
        // Main loop just tries to (re)connect
        'connect: loop {
            // Channel for the sender task. TODO: Find a way to remove this.
            let (mut snd_msg, mut rcv_msg) = mpsc::channel::<String>(100);

            snd_ev.try_send(IrcEv::Connecting).unwrap();

            //
            // Resolve IP address
            //

            let serv_name = server_info.addr.clone();
            let port = server_info.port;

            println!("Resolving address");

            let mut addr_iter = match tokio_executor::blocking::run(move || {
                (serv_name.as_str(), port).to_socket_addrs()
            })
            .await
            {
                Err(io_err) => {
                    snd_ev.try_send(IrcEv::IoErr(io_err)).unwrap();
                    // Wait 30 seconds before looping
                    tokio::timer::delay(tokio::clock::now() + Duration::from_secs(30)).await;
                    continue;
                }
                Ok(addr_iter) => addr_iter,
            };

            println!("Address resolved");

            let addr = match addr_iter.next() {
                None => {
                    snd_ev.try_send(IrcEv::CantResolveAddr).unwrap();
                    break;
                }
                Some(addr) => addr,
            };

            //
            // Establish TCP connection to the server
            //

            println!("Establishing connection ...");

            let stream = match TcpStream::connect(&addr).await {
                Err(io_err) => {
                    snd_ev.try_send(IrcEv::IoErr(io_err)).unwrap();
                    // Wait 30 seconds before looping
                    tokio::timer::delay(tokio::clock::now() + Duration::from_secs(30)).await;
                    continue;
                }
                Ok(stream) => stream,
            };

            println!("Done");

            let (mut read_half, mut write_half) = stream.split();

            //
            // Do the business
            //

            // Spawn a task for outgoing messages.
            let mut snd_ev_clone = snd_ev.clone();
            tokio::spawn(async move {
                while let Some(msg) = rcv_msg.next().await {
                    if let Err(io_err) = write_half.write_all(msg.as_str().as_bytes()).await {
                        println!("IO error when writing: {:?}", io_err);
                        snd_ev_clone.try_send(IrcEv::IoErr(io_err)).unwrap();
                        return;
                    }
                }
            });

            let mut parse_buf: Vec<u8> = Vec::with_capacity(1024);
            let mut irc_state = irc_state::IrcState::new(&server_info, &mut snd_msg);

            loop {
                let mut read_buf: [u8; 1024] = [0; 1024];

                select! {
                    cmd = rcv_cmd_fused.next() => {
                        match cmd {
                            None => {
                                println!("main loop: command channel terminated from the other end");
                                // That's OK, rcv_cmd_fused will never be ready again
                            }
                            Some(IrcCmd::Msg(msg)) => {
                                // FIXME something like this
                                println!(">>> {}", &msg[..msg.len()-2]);
                            }
                        }
                    }
                    bytes = read_half.read(&mut read_buf).fuse() => {
                        match bytes {
                            Err(io_err) => {
                                println!("main loop: error when reading from socket: {:?}", io_err);
                                snd_ev.try_send(IrcEv::IoErr(io_err)).unwrap();
                                snd_ev.try_send(IrcEv::Disconnected).unwrap();
                                continue 'connect;
                            }
                            Ok(bytes) => {
                                parse_buf.extend_from_slice(&read_buf[0..bytes]);
                                while let Some(msg) = wire::parse_irc_msg(&mut parse_buf) {
                                    println!("parsed msg: {:?}", msg);
                                    irc_state.update(&msg, &mut snd_ev, &mut snd_msg);
                                }
                            }
                        }
                    }
                }
            }
        }
    });

    Ok((IrcClient { msg_chan: snd_cmd }, rcv_ev))
}
<|endoftext|>


<commit_before>use crate::grammar::ast::{Conditional, eq::ASTEq};
use crate::grammar::model::{Fragment, HasFragment};
use nom::IResult;

impl<'s> Conditional<'s> {
    /// Parse a conditional expression in source code.
    pub fn parse(input: Fragment<'s>) -> IResult<Fragment<'s>, Self> {
        unimplemented!()
    }
}

impl<'s> HasFragment<'s> for Conditional<'s> {
    fn get_fragment(&self) -> Fragment<'s> {
        self.frag
    }
}

impl<'s> ASTEq for Conditional<'s> {
    fn ast_eq(fst: &Self, snd: &Self) -> bool {
        ASTEq::ast_eq(&fst.default, &snd.default);
        todo!()
    }
}<commit_msg>WIP Conditional Parsing<commit_after>use crate::grammar::ast::{Conditional, eq::ASTEq, Expression, Block};
use crate::grammar::model::{Fragment, HasFragment};
use nom::IResult;
use nom::bytes::complete::tag;
use nom::combinator::map;
use crate::grammar::parsers::with_input;
use nom::sequence::{preceded, pair, delimited, terminated};
use crate::grammar::parsers::whitespace::token_delimiter;

impl<'s> Conditional<'s> {
    /// `if` token in source code. This constant is unlikely to change.
    pub const IF: &'static str = "if";

    /// `else` token in source code. This constant is unlikely to change.
    pub const ELSE: &'static str = "else";

    // parse an expression followed by a block.
    fn parse_branch(input: Fragment<'s>) -> IResult<Fragment<'s>, (Expression<'s>, Block<'s>)> {
        pair(
            terminated(
                    Expression::parse,
                    token_delimiter
            ),
            Block::parse
        )(input)
    }

    // parse the if branch of a conditional expression.
    fn parse_if(input: Fragment<'s>) -> IResult<Fragment<'s>, (Expression<'s>, Block<'s>)> {
        preceded(
            pair(tag(Self::IF), token_delimiter),
            Self::parse_branch
        )(input)
    }

    /// Parse a conditional expression in source code.
    pub fn parse(input: Fragment<'s>) -> IResult<Fragment<'s>, Self> {
        map(
            with_input(
                pair(
                    preceded(
                        preceded(tag(Self::IF), token_delimiter),
                        pair(
                            Expression::parse,
                            Block::parse
                        )
                    ),

                ),
            || {

        })(input)
    }
}

impl<'s> HasFragment<'s> for Conditional<'s> {
    fn get_fragment(&self) -> Fragment<'s> {
        self.frag
    }
}

impl<'s> ASTEq for Conditional<'s> {
    fn ast_eq(fst: &Self, snd: &Self) -> bool {
        ASTEq::ast_eq(&fst.default, &snd.default);
        todo!()
    }
}<|endoftext|>


<commit_before>//! [POST /_matrix/federation/v1/get_missing_events/{roomId}](https://matrix.org/docs/spec/server_server/r0.1.4#post-matrix-federation-v1-get-missing-events-roomid)

use js_int::{uint, UInt};
use ruma_api::ruma_api;
use ruma_events::pdu::Pdu;
use ruma_identifiers::{EventId, RoomId};

ruma_api! {
    metadata: {
        description: "Retrieves previous events that the sender is missing.",
        method: POST,
        name: "get_missing_events",
        path: "/_matrix/federation/v1/get_missing_events/:room_id",
        rate_limited: false,
        authentication: ServerSignatures,
    }

    request: {
        /// The room ID to search in.
        #[ruma_api(path)]
        pub room_id: &'a RoomId,

        /// The maximum number of events to retrieve. Defaults to 10.
        #[serde(default = "default_limit", skip_serializing_if = "is_default_limit")]
        pub limit: UInt,

        /// The minimum depth of events to retrieve. Defaults to 0.
        #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
        pub min_depth: UInt,

        /// The latest event IDs that the sender already has. These are skipped when retrieving the previous events of `latest_events`.
        pub earliest_events: &'a [EventId],

        /// The event IDs to retrieve the previous events for.
        pub latest_events: &'a [EventId],
    }

    #[derive(Default)]
    response: {
        /// The missing PDUs.
        pub events: Vec<Pdu>
    }
}

impl<'a> Request<'a> {
    /// Creates a new `Request` for events in the given room with the given constraints.
    pub fn new(
        room_id: &'a RoomId,
        earliest_events: &'a [EventId],
        latest_events: &'a [EventId],
    ) -> Self {
        Self {
            room_id,
            limit: default_limit(),
            min_depth: UInt::default(),
            earliest_events,
            latest_events,
        }
    }
}

impl Response {
    /// Creates a new `Response` with the given events.
    pub fn new(events: Vec<Pdu>) -> Self {
        Self { events }
    }
}

fn default_limit() -> UInt {
    uint!(10)
}

fn is_default_limit(val: &UInt) -> bool {
    *val == default_limit()
}
<commit_msg>federation-api: Wrap events jn get_missing_events in Raw<commit_after>//! [POST /_matrix/federation/v1/get_missing_events/{roomId}](https://matrix.org/docs/spec/server_server/r0.1.4#post-matrix-federation-v1-get-missing-events-roomid)

use js_int::{uint, UInt};
use ruma_api::ruma_api;
use ruma_common::Raw;
use ruma_events::pdu::Pdu;
use ruma_identifiers::{EventId, RoomId};

ruma_api! {
    metadata: {
        description: "Retrieves previous events that the sender is missing.",
        method: POST,
        name: "get_missing_events",
        path: "/_matrix/federation/v1/get_missing_events/:room_id",
        rate_limited: false,
        authentication: ServerSignatures,
    }

    request: {
        /// The room ID to search in.
        #[ruma_api(path)]
        pub room_id: &'a RoomId,

        /// The maximum number of events to retrieve. Defaults to 10.
        #[serde(default = "default_limit", skip_serializing_if = "is_default_limit")]
        pub limit: UInt,

        /// The minimum depth of events to retrieve. Defaults to 0.
        #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
        pub min_depth: UInt,

        /// The latest event IDs that the sender already has. These are skipped when retrieving the previous events of `latest_events`.
        pub earliest_events: &'a [EventId],

        /// The event IDs to retrieve the previous events for.
        pub latest_events: &'a [EventId],
    }

    #[derive(Default)]
    response: {
        /// The missing PDUs.
        pub events: Vec<Raw<Pdu>>
    }
}

impl<'a> Request<'a> {
    /// Creates a new `Request` for events in the given room with the given constraints.
    pub fn new(
        room_id: &'a RoomId,
        earliest_events: &'a [EventId],
        latest_events: &'a [EventId],
    ) -> Self {
        Self {
            room_id,
            limit: default_limit(),
            min_depth: UInt::default(),
            earliest_events,
            latest_events,
        }
    }
}

impl Response {
    /// Creates a new `Response` with the given events.
    pub fn new(events: Vec<Raw<Pdu>>) -> Self {
        Self { events }
    }
}

fn default_limit() -> UInt {
    uint!(10)
}

fn is_default_limit(val: &UInt) -> bool {
    *val == default_limit()
}
<|endoftext|>


<commit_before>use geojson::Geometry;
use serde::Serialize;
use tracing::{debug, instrument};
use warp::http::StatusCode;
use warp::reply::{json, with_status};

use crate::adapters::primary::bragi::api::ForwardGeocoderExplainQuery;
use crate::adapters::primary::{
    bragi::api::{
        BragiStatus, ElasticsearchStatus, ForwardGeocoderQuery, MimirStatus, ReverseGeocoderQuery,
        StatusResponseBody, Type,
    },
    common::{
        dsl, filters, geocoding::Feature, geocoding::FromWithLang, geocoding::GeocodeJsonResponse,
        settings,
    },
};
use crate::domain::model::configuration::{root_doctype, root_doctype_dataset};
use crate::domain::model::query::Query;
use crate::domain::ports::primary::explain_query::ExplainDocument;
use crate::domain::ports::primary::search_documents::SearchDocuments;
use crate::domain::ports::primary::status::Status;
use common::document::ContainerDocument;
use places::{addr::Addr, admin::Admin, poi::Poi, stop::Stop, street::Street, Place};

const VERSION: &str = env!("CARGO_PKG_VERSION");

#[instrument(skip(client, settings))]
pub async fn forward_geocoder<S>(
    params: ForwardGeocoderQuery,
    geometry: Option<Geometry>,
    client: S,
    settings: settings::QuerySettings,
) -> Result<impl warp::Reply, warp::Rejection>
where
    S: SearchDocuments,
    S::Document: Serialize + Into<serde_json::Value>,
{
    let q = params.q.clone();
    let timeout = params.timeout;
    let es_indices_to_search_in = build_es_indices_to_search(&params);
    let filters = filters::Filters::from((params, geometry));
    let dsl = dsl::build_query(&q, filters.clone(), &["fr"], &settings);

    debug!("{}", serde_json::to_string(&dsl).unwrap());

    match client
        .search_documents(
            es_indices_to_search_in,
            Query::QueryDSL(dsl),
            filters.limit,
            timeout,
        )
        .await
    {
        Ok(res) => {
            let places: Result<Vec<Place>, serde_json::Error> = res
                .into_iter()
                .map(|json| serde_json::from_value::<Place>(json.into()))
                .collect();

            match places {
                Ok(places) => {
                    let features = places
                        .into_iter()
                        .map(|p| Feature::from_with_lang(p, None)) // FIXME lang: None
                        .collect();
                    let resp = GeocodeJsonResponse::new(q, features);
                    Ok(with_status(json(&resp), StatusCode::OK))
                }
                Err(err) => Ok(with_status(
                    json(&format!(
                        "Error while searching {}: {}",
                        &q,
                        err.to_string()
                    )),
                    StatusCode::INTERNAL_SERVER_ERROR,
                )),
            }
        }
        Err(err) => Ok(with_status(
            json(&format!(
                "Error while searching {}: {}",
                &q,
                err.to_string()
            )),
            StatusCode::INTERNAL_SERVER_ERROR,
        )),
    }
}

#[instrument(skip(client, settings))]
pub async fn forward_geocoder_explain<S>(
    params: ForwardGeocoderExplainQuery,
    geometry: Option<Geometry>,
    client: S,
    settings: settings::QuerySettings,
) -> Result<impl warp::Reply, warp::Rejection>
where
    S: ExplainDocument,
    S::Document: Serialize + Into<serde_json::Value>,
{
    let q = params.query.q.clone();
    let filters = filters::Filters::from((params.query, geometry));
    let dsl = dsl::build_query(&q, filters, &["fr"], &settings);

    debug!("{}", serde_json::to_string(&dsl).unwrap());

    match client
        .explain_document(Query::QueryDSL(dsl), params.doc_id, params.doc_type)
        .await
    {
        Ok(res) => Ok(with_status(json(&res), StatusCode::OK)),
        Err(err) => Ok(with_status(
            json(&format!(
                "Error while searching {}: {}",
                &q,
                err.to_string()
            )),
            StatusCode::INTERNAL_SERVER_ERROR,
        )),
    }
}

pub async fn reverse_geocoder<S>(
    params: ReverseGeocoderQuery,
    client: S,
    settings: settings::QuerySettings,
) -> Result<impl warp::Reply, warp::Rejection>
where
    S: SearchDocuments,
    S::Document: Serialize + Into<serde_json::Value>,
{
    let distance = format!("{}m", settings.reverse_query.radius);
    let dsl = dsl::build_reverse_query(&distance, params.lat, params.lon);

    match client
        .search_documents(
            vec![
                String::from(Street::static_doc_type()),
                String::from(Addr::static_doc_type()),
            ],
            Query::QueryDSL(dsl),
            params.limit,
            params.timeout,
        )
        .await
    {
        Ok(res) => {
            let places = res
                .into_iter()
                .map(|json| serde_json::from_value::<Place>(json.into()).unwrap())
                .collect();

            let resp = GeocodeJsonResponse::from_with_lang(places, None);
            Ok(with_status(json(&resp), StatusCode::OK))
        }
        Err(err) => Ok(with_status(
            json(&format!(
                "Error while reverse searching: {}",
                err.to_string()
            )),
            StatusCode::INTERNAL_SERVER_ERROR,
        )),
    }
}

pub async fn status<S>(client: S, url: String) -> Result<impl warp::Reply, warp::Rejection>
where
    S: Status,
{
    match client.status().await {
        Ok(res) => {
            let resp = StatusResponseBody {
                bragi: BragiStatus {
                    version: VERSION.to_string(),
                },
                mimir: MimirStatus {
                    version: res.version,
                },
                elasticsearch: ElasticsearchStatus {
                    version: res.storage.version,
                    health: res.storage.health.to_string(),
                    url,
                },
            };
            Ok(with_status(json(&resp), StatusCode::OK))
        }
        Err(err) => Ok(with_status(
            json(&format!("Error while querying status: {}", err.to_string())),
            StatusCode::INTERNAL_SERVER_ERROR,
        )),
    }
}

fn build_es_indices_to_search(query: &ForwardGeocoderQuery) -> Vec<String> {
    // some specific types are requested,
    // let's search only for these types of objects
    if let Some(types) = &query.types {
        let mut indices = Vec::new();
        for doc_type in types.iter() {
            match doc_type {
                Type::House => indices.push(root_doctype(Addr::static_doc_type())),
                Type::Street => indices.push(root_doctype(Street::static_doc_type())),
                Type::Zone => indices.push(root_doctype(Admin::static_doc_type())),
                Type::Poi => {
                    let doc_type_str = Poi::static_doc_type();
                    // if some poi_dataset are specified
                    // we search for poi only in the corresponding es indices
                    if let Some(poi_datasets) = &query.poi_dataset {
                        for poi_dataset in poi_datasets.iter() {
                            indices.push(root_doctype_dataset(doc_type_str, poi_dataset));
                        }
                    } else {
                        // no poi_dataset specified
                        // we search in the global alias for all poi
                        indices.push(root_doctype(doc_type_str));
                    }
                }
                Type::StopArea => {
                    // if some pt_dataset are specified
                    // we search for stops only in the corresponding es indices
                    let doc_type_str = Stop::static_doc_type();
                    if let Some(pt_datasets) = &query.pt_dataset {
                        for pt_dataset in pt_datasets.iter() {
                            indices.push(root_doctype_dataset(doc_type_str, pt_dataset));
                        }
                    } else {
                        // no pt_dataset specified
                        // we search in the global alias for all stops
                        indices.push(root_doctype(doc_type_str));
                    }
                }
            }
        }
        indices
    }
    // no types specified, we search for all objects in all indices
    else {
        vec![
            root_doctype(Admin::static_doc_type()),
            root_doctype(Street::static_doc_type()),
            root_doctype(Addr::static_doc_type()),
            root_doctype(Stop::static_doc_type()),
            root_doctype(Poi::static_doc_type()),
        ]
    }
}
<commit_msg>adapt reverse_geocoder handler<commit_after>use geojson::Geometry;
use serde::Serialize;
use tracing::{debug, instrument};
use warp::http::StatusCode;
use warp::reply::{json, with_status};

use crate::adapters::primary::bragi::api::ForwardGeocoderExplainQuery;
use crate::adapters::primary::{
    bragi::api::{
        BragiStatus, ElasticsearchStatus, ForwardGeocoderQuery, MimirStatus, ReverseGeocoderQuery,
        StatusResponseBody, Type,
    },
    common::{
        dsl, filters, geocoding::Feature, geocoding::FromWithLang, geocoding::GeocodeJsonResponse,
        settings,
    },
};
use crate::domain::model::configuration::{root_doctype, root_doctype_dataset};
use crate::domain::model::query::Query;
use crate::domain::ports::primary::explain_query::ExplainDocument;
use crate::domain::ports::primary::search_documents::SearchDocuments;
use crate::domain::ports::primary::status::Status;
use common::document::ContainerDocument;
use places::{addr::Addr, admin::Admin, poi::Poi, stop::Stop, street::Street, Place};

const VERSION: &str = env!("CARGO_PKG_VERSION");

#[instrument(skip(client, settings))]
pub async fn forward_geocoder<S>(
    params: ForwardGeocoderQuery,
    geometry: Option<Geometry>,
    client: S,
    settings: settings::QuerySettings,
) -> Result<impl warp::Reply, warp::Rejection>
where
    S: SearchDocuments,
    S::Document: Serialize + Into<serde_json::Value>,
{
    let q = params.q.clone();
    let timeout = params.timeout;
    let es_indices_to_search_in = build_es_indices_to_search(&params);
    let filters = filters::Filters::from((params, geometry));
    let dsl = dsl::build_query(&q, filters.clone(), &["fr"], &settings);

    debug!("{}", serde_json::to_string(&dsl).unwrap());

    match client
        .search_documents(
            es_indices_to_search_in,
            Query::QueryDSL(dsl),
            filters.limit,
            timeout,
        )
        .await
    {
        Ok(res) => {
            let places: Result<Vec<Place>, serde_json::Error> = res
                .into_iter()
                .map(|json| serde_json::from_value::<Place>(json.into()))
                .collect();

            match places {
                Ok(places) => {
                    let features = places
                        .into_iter()
                        .map(|p| Feature::from_with_lang(p, None)) // FIXME lang: None
                        .collect();
                    let resp = GeocodeJsonResponse::new(q, features);
                    Ok(with_status(json(&resp), StatusCode::OK))
                }
                Err(err) => Ok(with_status(
                    json(&format!(
                        "Error while searching {}: {}",
                        &q,
                        err.to_string()
                    )),
                    StatusCode::INTERNAL_SERVER_ERROR,
                )),
            }
        }
        Err(err) => Ok(with_status(
            json(&format!(
                "Error while searching {}: {}",
                &q,
                err.to_string()
            )),
            StatusCode::INTERNAL_SERVER_ERROR,
        )),
    }
}

#[instrument(skip(client, settings))]
pub async fn forward_geocoder_explain<S>(
    params: ForwardGeocoderExplainQuery,
    geometry: Option<Geometry>,
    client: S,
    settings: settings::QuerySettings,
) -> Result<impl warp::Reply, warp::Rejection>
where
    S: ExplainDocument,
    S::Document: Serialize + Into<serde_json::Value>,
{
    let q = params.query.q.clone();
    let filters = filters::Filters::from((params.query, geometry));
    let dsl = dsl::build_query(&q, filters, &["fr"], &settings);

    debug!("{}", serde_json::to_string(&dsl).unwrap());

    match client
        .explain_document(Query::QueryDSL(dsl), params.doc_id, params.doc_type)
        .await
    {
        Ok(res) => Ok(with_status(json(&res), StatusCode::OK)),
        Err(err) => Ok(with_status(
            json(&format!(
                "Error while searching {}: {}",
                &q,
                err.to_string()
            )),
            StatusCode::INTERNAL_SERVER_ERROR,
        )),
    }
}

pub async fn reverse_geocoder<S>(
    params: ReverseGeocoderQuery,
    client: S,
    settings: settings::QuerySettings,
) -> Result<impl warp::Reply, warp::Rejection>
where
    S: SearchDocuments,
    S::Document: Serialize + Into<serde_json::Value>,
{
    let distance = format!("{}m", settings.reverse_query.radius);
    let dsl = dsl::build_reverse_query(&distance, params.lat, params.lon);

    let es_indices_to_search_in = vec![
        root_doctype(Street::static_doc_type()),
        root_doctype(Addr::static_doc_type()),
    ];

    match client
        .search_documents(
            es_indices_to_search_in,
            Query::QueryDSL(dsl),
            params.limit,
            params.timeout,
        )
        .await
    {
        Ok(res) => {
            let places = res
                .into_iter()
                .map(|json| serde_json::from_value::<Place>(json.into()).unwrap())
                .collect();

            let resp = GeocodeJsonResponse::from_with_lang(places, None);
            Ok(with_status(json(&resp), StatusCode::OK))
        }
        Err(err) => Ok(with_status(
            json(&format!(
                "Error while reverse searching: {}",
                err.to_string()
            )),
            StatusCode::INTERNAL_SERVER_ERROR,
        )),
    }
}

pub async fn status<S>(client: S, url: String) -> Result<impl warp::Reply, warp::Rejection>
where
    S: Status,
{
    match client.status().await {
        Ok(res) => {
            let resp = StatusResponseBody {
                bragi: BragiStatus {
                    version: VERSION.to_string(),
                },
                mimir: MimirStatus {
                    version: res.version,
                },
                elasticsearch: ElasticsearchStatus {
                    version: res.storage.version,
                    health: res.storage.health.to_string(),
                    url,
                },
            };
            Ok(with_status(json(&resp), StatusCode::OK))
        }
        Err(err) => Ok(with_status(
            json(&format!("Error while querying status: {}", err.to_string())),
            StatusCode::INTERNAL_SERVER_ERROR,
        )),
    }
}

fn build_es_indices_to_search(query: &ForwardGeocoderQuery) -> Vec<String> {
    // some specific types are requested,
    // let's search only for these types of objects
    if let Some(types) = &query.types {
        let mut indices = Vec::new();
        for doc_type in types.iter() {
            match doc_type {
                Type::House => indices.push(root_doctype(Addr::static_doc_type())),
                Type::Street => indices.push(root_doctype(Street::static_doc_type())),
                Type::Zone => indices.push(root_doctype(Admin::static_doc_type())),
                Type::Poi => {
                    let doc_type_str = Poi::static_doc_type();
                    // if some poi_dataset are specified
                    // we search for poi only in the corresponding es indices
                    if let Some(poi_datasets) = &query.poi_dataset {
                        for poi_dataset in poi_datasets.iter() {
                            indices.push(root_doctype_dataset(doc_type_str, poi_dataset));
                        }
                    } else {
                        // no poi_dataset specified
                        // we search in the global alias for all poi
                        indices.push(root_doctype(doc_type_str));
                    }
                }
                Type::StopArea => {
                    // if some pt_dataset are specified
                    // we search for stops only in the corresponding es indices
                    let doc_type_str = Stop::static_doc_type();
                    if let Some(pt_datasets) = &query.pt_dataset {
                        for pt_dataset in pt_datasets.iter() {
                            indices.push(root_doctype_dataset(doc_type_str, pt_dataset));
                        }
                    } else {
                        // no pt_dataset specified
                        // we search in the global alias for all stops
                        indices.push(root_doctype(doc_type_str));
                    }
                }
            }
        }
        indices
    }
    // no types specified, we search for all objects in all indices
    else {
        vec![
            root_doctype(Admin::static_doc_type()),
            root_doctype(Street::static_doc_type()),
            root_doctype(Addr::static_doc_type()),
            root_doctype(Stop::static_doc_type()),
            root_doctype(Poi::static_doc_type()),
        ]
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-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.
#![feature(macro_rules)]

// ignore-pretty very bad with line comments

extern crate sync;

use std::io;
use sync::Future;

static ITER: int = 50;
static LIMIT: f64 = 2.0;

macro_rules! core_loop(
    ($pow:expr ~ $mask:expr: $ctx:ident, $b:ident) => (
        {
            let r = $ctx.r;
            let i = $ctx.i;

            $ctx.r = r * r - i * i + $ctx.init_r;
            $ctx.i = 2.0 * r * i + $ctx.init_i;

            if r * r + i * i > LIMIT * LIMIT {
                $b |= $pow;
                if $b == $mask { break; }
            }
        }
    );
)

#[inline(always)]
fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
    struct Context { r: f64, i: f64, init_i: f64, init_r: f64 }
    impl Context {
        #[inline(always)]
        fn new(i: f64, r: f64) -> Context {
            Context { r: r, i: i, init_r: r, init_i: i }
        }
    }

    let mut cur_byte;
    let mut i;
    let mut bit_1;
    let mut bit_2;
    let mut b;
    for chunk_init_r in vec_init_r.chunks(8) {
        cur_byte = 0xff;
        i = 0;

        while i < 8 {
            bit_1 = Context::new(init_i, chunk_init_r[i]);
            bit_2 = Context::new(init_i, chunk_init_r[i + 1]);

            b = 0;
            for _ in range(0, ITER) {
                core_loop!(2 ~ 3: bit_1, b);
                core_loop!(1 ~ 3: bit_2, b);
            }

            cur_byte = (cur_byte << 2) + b;
            i += 2;
        }
        res.push(cur_byte^-1);
    }
}

fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
    // Ensure w and h are multiples of 8.
    let w = (w + 7) / 8 * 8;
    let h = w;
    let inverse_w_doubled = 2.0 / w as f64;
    let inverse_h_doubled = 2.0 / h as f64;
    let chunk_size = h / 16;

    let data: Vec<Future<Vec<u8>>> = range(0u, 16).map(|i| Future::spawn(proc () {
        let vec_init_r = Vec::from_fn(w, |x| (x as f64) * inverse_w_doubled - 1.5);
        let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
        for y in range(i * chunk_size, (i + 1) * chunk_size) {
            let init_i = (y as f64) * inverse_h_doubled - 1.0;
            write_line(init_i, vec_init_r.as_slice(), &mut res);
        }
        res
    })).collect();

    try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
    for res in data.move_iter() {
        try!(out.write(res.unwrap().as_slice()));
    }
    out.flush()
}

fn main() {
    let args = std::os::args();
    let args = args.as_slice();
    let res = if args.len() < 2 {
        println!("Test mode: do not dump the image because it's not utf8, \
                  which interferes with the test runner.");
        mandelbrot(1000, std::io::util::NullWriter)
    } else {
        mandelbrot(from_str(args[1]).unwrap(), std::io::stdout())
    };
    res.unwrap();
}
<commit_msg>shootout-mandelbrot: Precalc initial values & use SIMD in the main loop. +80-100%<commit_after>// Copyright 2012-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.
#![feature(macro_rules)]
#![feature(simd)]
#![allow(experimental)]

// ignore-pretty very bad with line comments

extern crate sync;

use std::io;
use std::os;
use std::unstable::simd::f64x2;
use sync::Future;
use sync::Arc;

static ITER: int = 50;
static LIMIT: f64 = 2.0;
static WORKERS: uint = 16;

#[inline(always)]
fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
    assert!(WORKERS % 2 == 0);

    // Ensure w and h are multiples of 8.
    let w = (w + 7) / 8 * 8;
    let h = w;

    let chunk_size = h / WORKERS;

    // Account for remainders in workload division, e.g. 1000 / 16 = 62.5
    let first_chunk_size = if h % WORKERS != 0 {
        chunk_size + h % WORKERS
    } else {
        chunk_size
    };

    // precalc values
    let inverse_w_doubled = 2.0 / w as f64;
    let inverse_h_doubled = 2.0 / h as f64;
    let v_inverses = f64x2(inverse_w_doubled, inverse_h_doubled);
    let v_consts = f64x2(1.5, 1.0);

    // A lot of this code assumes this (so do other lang benchmarks)
    assert!(w == h);
    let mut precalc_r = Vec::with_capacity(w);
    let mut precalc_i = Vec::with_capacity(h);

    let precalc_futures = Vec::from_fn(WORKERS, |i| {
        Future::spawn(proc () {
            let mut rs = Vec::with_capacity(w / WORKERS);
            let mut is = Vec::with_capacity(w / WORKERS);

            let start = i * chunk_size;
            let end = if i == 0 {
                first_chunk_size
            } else {
                (i + 1) * chunk_size
            };

            // This assumes w == h
            for x in range(start, end) {
                let xf = x as f64;
                let xy = f64x2(xf, xf);

                let f64x2(r, i) = xy * v_inverses - v_consts;
                rs.push(r);
                is.push(i);
            }

            (rs, is)
        })
    });

    for res in precalc_futures.move_iter() {
        let (rs, is) = res.unwrap();
        precalc_r.push_all_move(rs);
        precalc_i.push_all_move(is);
    }

    assert_eq!(precalc_r.len(), w);
    assert_eq!(precalc_i.len(), h);

    let arc_init_r = Arc::new(precalc_r);
    let arc_init_i = Arc::new(precalc_i);

    let data = Vec::from_fn(WORKERS, |i| {
        let vec_init_r = arc_init_r.clone();
        let vec_init_i = arc_init_i.clone();

        Future::spawn(proc () {
            let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
            let init_r_slice = vec_init_r.as_slice();
            for &init_i in vec_init_i.slice(i * chunk_size, (i + 1) * chunk_size).iter() {
                write_line(init_i, init_r_slice, &mut res);
            }

            res
        })
    });

    try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
    for res in data.move_iter() {
        try!(out.write(res.unwrap().as_slice()));
    }
    out.flush()
}

fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
    let v_init_i : f64x2 = f64x2(init_i, init_i);
    let v_2 : f64x2 = f64x2(2.0, 2.0);
    static LIMIT_SQUARED: f64 = LIMIT * LIMIT;

    for chunk_init_r in vec_init_r.chunks(8) {
        let mut cur_byte = 0xff;
        let mut i = 0;

        while i < 8 {
            let v_init_r = f64x2(chunk_init_r[i], chunk_init_r[i + 1]);
            let mut cur_r = v_init_r;
            let mut cur_i = v_init_i;
            let mut r_sq = v_init_r * v_init_r;
            let mut i_sq = v_init_i * v_init_i;

            let mut b = 0;
            for _ in range(0, ITER) {
                let r = cur_r;
                let i = cur_i;

                cur_i = v_2 * r * i + v_init_i;
                cur_r = r_sq - i_sq + v_init_r;

                let f64x2(bit1, bit2) = r_sq + i_sq;

                if bit1 > LIMIT_SQUARED {
                    b |= 2;
                    if b == 3 { break; }
                }

                if bit2 > LIMIT_SQUARED {
                    b |= 1;
                    if b == 3 { break; }
                }

                r_sq = cur_r * cur_r;
                i_sq = cur_i * cur_i;
            }

            cur_byte = (cur_byte << 2) + b;
            i += 2;
        }

        res.push(cur_byte^-1);
    }
}

fn main() {
    let args = os::args();
    let args = args.as_slice();
    let res = if args.len() < 2 {
        println!("Test mode: do not dump the image because it's not utf8, \
                  which interferes with the test runner.");
        mandelbrot(1000, io::util::NullWriter)
    } else {
        mandelbrot(from_str(args[1]).unwrap(), io::stdout())
    };
    res.unwrap();
}
<|endoftext|>