<commit_before>#[crate_id = "vm#0.0"];
#[crate_type = "bin"];
#[feature(managed_boxes, macro_rules, globs)];
extern mod extra;
use std::hashmap::HashMap;
use std::rc::Rc;
use std::path::Path;
use std::io::File;
use std::str::{from_utf8};
use typecheck::TypeEnvironment;
use compiler::{Compiler, Assembly,
    Instruction, Add, Sub, Multiply, Divide, Remainder, Push, PushGlobal, PushInt, Mkap, Eval, Unwind, Update, Pop, Slide, Split, Pack, CaseJump, Jump,
    SuperCombinator};
use parser::Parser;

mod compiler;
mod typecheck;
mod lexer;
mod parser;
mod module;
mod graph;

struct Scope<'a, T> {
    variables: HashMap<~str, T>,
    parent: Option<&'a Scope<'a, T>>
}

impl <'a, T> Scope<'a, T> {

    fn new() -> Scope<T> {
        Scope { variables : HashMap::new(), parent : None }
    }

    fn insert(&mut self, identifier : ~str, value : T) {
        self.variables.insert(identifier, value);
    }

    fn find(&'a self, identifier : &str) -> Option<&'a T> {
       match self.variables.find_equiv(&identifier) {
            Some(var) => Some(var),
            None => match self.parent {
                Some(parent) => parent.find(identifier),
                None => None
            }
       }
    }

    fn child(&'a self) -> Scope<'a, T> {
        Scope { variables : HashMap::new(), parent : Some(self) }
    }
}

#[deriving(Clone)]
enum Node<'a> {
    Application(Rc<Node<'a>>, Rc<Node<'a>>),
    Int(int),
    Combinator(&'a SuperCombinator),
    Indirection(Rc<Node<'a>>),
    Constructor(u16, ~[Rc<Node<'a>>])
}

struct VM<'a> {
    assembly : Assembly,
    heap : ~[Node<'a>]
}

impl <'a> VM<'a> {
    fn new() -> VM {
        VM { assembly : Assembly { superCombinators : ~[] }, heap : ~[] }
    }

    fn evaluate(&'a self, code: &[Instruction]) -> Node<'a> {
        let mut stack = ~[];
        self.execute(&mut stack, code);
        static evalCode : &'static [Instruction] = &[Eval];
        self.execute(&mut stack, evalCode);
        assert_eq!(stack.len(), 1);
        stack[0].borrow().clone()
    }

    fn execute(&'a self, stack : &mut ~[Rc<Node<'a>>], code : &[Instruction]) {
        debug!("----------------------------");
        debug!("Entering frame with stack");
        for x in stack.iter() {
            debug!("{:?}", x.borrow());
        }
        debug!("");
        let mut i = 0;
        while i < code.len() {
            debug!("Executing instruction : {:?}", code[i]);
            match &code[i] {
                &Add => primitive(stack, |l, r| { l + r }),
                &Sub => primitive(stack, |l, r| { l - r }),
                &Multiply => primitive(stack, |l, r| { l * r }),
                &Divide => primitive(stack, |l, r| { l / r }),
                &Remainder => primitive(stack, |l, r| { l % r }),
                &PushInt(value) => { stack.push(Rc::new(Int(value))); }
                &Push(index) => {
                    let x = stack[index].clone();
                    debug!("Pushed {:?}", x.borrow());
                    for j in range(0, stack.len()) {
                        debug!(" {}  {:?}", j, stack[j].borrow());
                    }
                    stack.push(x);
                }
                &PushGlobal(index) => {
                    match &self.assembly.superCombinators[index] {
                        &(_, ref sc) => stack.push(Rc::new(Combinator(sc)))
                    }
                }
                &Mkap => {
                    let func = stack.pop();
                    let arg = stack.pop();
                    debug!("Mkap {:?} {:?}", func.borrow(), arg.borrow());
                    stack.push(Rc::new(Application(func, arg)));
                }
                &Eval => {
                    static unwindCode : &'static [Instruction] = &[Unwind];
                    let mut newStack = ~[stack.pop()];
                    self.execute(&mut newStack, unwindCode);
                    assert_eq!(newStack.len(), 1);
                    stack.push(newStack.pop());
                }
                &Pop(num) => {
                    for _ in range(0, num) {
                        stack.pop();
                    }
                }
                &Update(index) => {
                    stack[index] = Rc::new(Indirection(stack[stack.len() - 1].clone()));
                }
                &Unwind => {
                    match (*stack[stack.len() - 1].borrow()).clone() {
                        Application(func, _) => {
                            stack.push(func);
                            i -= 1;//Redo the unwind instruction
                        }
                        Combinator(comb) => {
                            if stack.len() - 1 < comb.arity as uint {
                                while stack.len() > 1 {
                                    stack.pop();
                                }
                            }
                            else {
                                for j in range(stack.len() - (comb.arity as uint) - 1, stack.len() - 1) {
                                    stack[j] = match stack[j].borrow() {
                                        &Application(_, ref arg) => arg.clone(),
                                        _ => fail!("Expected Application")
                                    };
                                }
                                let mut newStack = ~[];
                                for i in range(0, comb.arity as uint) {
                                    let index = stack.len() - i - 2;
                                    newStack.push(stack[index].clone());
                                }

                                debug!("Call");
                                for j in range(0, newStack.len()) {
                                    debug!(" {}  {:?}", j, newStack[j].borrow());
                                }
                                self.execute(&mut newStack, comb.instructions);
                                assert_eq!(newStack.len(), 1);
                                for _ in range(0, comb.arity + 1) {
                                    stack.pop();
                                }
                                stack.push(newStack.pop());
                            }
                        }
                        Indirection(node) => {
                            stack[stack.len() - 1] = node;
                            i -= 1;
                        }
                        _ => ()
                    }
                }
                &Slide(size) => {
                    let top = stack.pop();
                    for _ in range(0, size) {
                        stack.pop();
                    }
                    stack.push(top);
                }
                &Split(_) => {
                    let x = stack.pop();
                    match x.borrow() {
                        &Constructor(_, ref fields) => {
                            for field in fields.iter() {
                                stack.push(field.clone());
                            }
                        }
                        _ => fail!("Expected constructor in Split instruction")
                    }
                }
                &Pack(tag, arity) => {
                    let args = std::vec::from_fn(arity as uint, |_| stack.pop());
                    stack.push(Rc::new(Constructor(tag, args)));
                }
                &CaseJump(jump_tag) => {
                    match stack[stack.len() - 1].borrow() {
                        &Constructor(tag, _) => {
                            if jump_tag != tag as uint {
                                i += 1;//Skip the jump instruction
                            }
                        }
                        _ => fail!("Expected constructor when executing CaseJump")
                    }
                }
                &Jump(to) => {
                    i = to - 1;
                }
                //undefined => fail!("Use of undefined instruction {:?}", undefined)
            }
            i += 1;
        }
        debug!("End frame");
        debug!("--------------------------");
    }
}

fn primitive(stack: &mut ~[Rc<Node>], f: |int, int| -> int) {
    let r = stack.pop();
    let l = stack.pop();
    match (l.borrow(), r.borrow()) {
        (&Int(lhs), &Int(rhs)) => stack.push(Rc::new(Int(f(lhs, rhs)))),
        (lhs, rhs) => fail!("Expected fully evaluted numbers in primitive instruction\n LHS: {:?}\nRHS: {:?} ", lhs, rhs)
    }
}

fn main() {
    let arguments = std::os::args();
    match arguments {
        [_, expr_str] => {
            let mut parser = Parser::new(expr_str.chars());
            let mut expr = parser.expression_();

            let mut type_env = TypeEnvironment::new();
            type_env.typecheck(&mut expr);

            let mut compiler = Compiler::new();
            let instr = compiler.compileExpression(&expr);

            let vm = VM::new();
            let mut stack = ~[];
            vm.execute(&mut stack, instr);
            println!("{:?}", stack[0].borrow());
        }
        [_, ~"-l", filename] => {
            let path = &Path::new(filename);
            let s  = File::open(path).read_to_end();
            let contents : &str = from_utf8(s);
            let result = execute_main(contents.chars());
            match result {
                Some(x) => println!("{:?}", x),
                None => println!("Error running file {:?}", path)
            }
        }
        _ => return println!("Expected one argument which is the expression or 2 arguments where the first is -l and the second the file to run (needs a main function)")
    }
}

#[deriving(Eq)]
enum VMResult {
    IntResult(int),
    ConstructorResult(u16, ~[VMResult])
}

fn compile_iter<T : Iterator<char>>(iterator: T) -> Assembly {
    let mut parser = Parser::new(iterator);
    let mut module = parser.module();

    let mut typer = TypeEnvironment::new();
    typer.typecheck_module(&mut module);

    let mut compiler = Compiler::new();
    compiler.compileModule(&module)
}

fn extract_result(node: Node) -> Option<VMResult> {
    match node {
        Constructor(tag, fields) => {
            let mut result = ~[];
            for field in fields.iter() {
                match extract_result(field.borrow().clone()) {
                    Some(x) => result.push(x),
                    None => return None
                }
            }
            Some(ConstructorResult(tag, result))
        }
        Int(i) => Some(IntResult(i)),
        x => {
            println!("Can't evalute result to {:?}", x);
            None
        }
    }
}

fn execute_main<T : Iterator<char>>(iterator: T) -> Option<VMResult> {
    let mut vm = VM::new();
    vm.assembly = compile_iter(iterator);
    let x = vm.assembly.superCombinators.iter().find(|& &(ref name, _)| *name == ~"main");
    match x {
        Some(&(_, ref sc)) => {
            assert!(sc.arity == 0);
            let result = vm.evaluate(sc.instructions);
            extract_result(result)
        }
        None => None
    }
}

#[test]
fn test_primitive()
{
    assert_eq!(execute_main("main = primIntAdd 10 5".chars()), Some(IntResult(15)));
    assert_eq!(execute_main("main = primIntSubtract 7 (primIntMultiply 2 3)".chars()), Some(IntResult(1)));
    assert_eq!(execute_main("main = primIntDivide 10 (primIntRemainder 6 4)".chars()), Some(IntResult(5)));
}

#[test]
fn test_function()
{
    let module =
r"mult2 x = primIntMultiply x 2

main = mult2 10";
    assert_eq!(execute_main(module.chars()), Some(IntResult(20)));

    let module2 =
r"mult2 x = primIntMultiply x 2

add x y = primIntAdd y x

main = add 3 (mult2 10)";
    assert_eq!(execute_main(module2.chars()), Some(IntResult(23)));
}
#[test]
fn test_case()
{
    let module =
r"mult2 x = primIntMultiply x 2

main = case [mult2 123, 0] of
    : x xs -> x
    [] -> 10";
    assert_eq!(execute_main(module.chars()), Some(IntResult(246)));
}
<commit_msg>Added test for using data types in the vm<commit_after>#[crate_id = "vm#0.0"];
#[crate_type = "bin"];
#[feature(managed_boxes, macro_rules, globs)];
extern mod extra;
use std::hashmap::HashMap;
use std::rc::Rc;
use std::path::Path;
use std::io::File;
use std::str::{from_utf8};
use typecheck::TypeEnvironment;
use compiler::{Compiler, Assembly,
    Instruction, Add, Sub, Multiply, Divide, Remainder, Push, PushGlobal, PushInt, Mkap, Eval, Unwind, Update, Pop, Slide, Split, Pack, CaseJump, Jump,
    SuperCombinator};
use parser::Parser;

mod compiler;
mod typecheck;
mod lexer;
mod parser;
mod module;
mod graph;

struct Scope<'a, T> {
    variables: HashMap<~str, T>,
    parent: Option<&'a Scope<'a, T>>
}

impl <'a, T> Scope<'a, T> {

    fn new() -> Scope<T> {
        Scope { variables : HashMap::new(), parent : None }
    }

    fn insert(&mut self, identifier : ~str, value : T) {
        self.variables.insert(identifier, value);
    }

    fn find(&'a self, identifier : &str) -> Option<&'a T> {
       match self.variables.find_equiv(&identifier) {
            Some(var) => Some(var),
            None => match self.parent {
                Some(parent) => parent.find(identifier),
                None => None
            }
       }
    }

    fn child(&'a self) -> Scope<'a, T> {
        Scope { variables : HashMap::new(), parent : Some(self) }
    }
}

#[deriving(Clone)]
enum Node<'a> {
    Application(Rc<Node<'a>>, Rc<Node<'a>>),
    Int(int),
    Combinator(&'a SuperCombinator),
    Indirection(Rc<Node<'a>>),
    Constructor(u16, ~[Rc<Node<'a>>])
}

struct VM<'a> {
    assembly : Assembly,
    heap : ~[Node<'a>]
}

impl <'a> VM<'a> {
    fn new() -> VM {
        VM { assembly : Assembly { superCombinators : ~[] }, heap : ~[] }
    }

    fn evaluate(&'a self, code: &[Instruction]) -> Node<'a> {
        let mut stack = ~[];
        self.execute(&mut stack, code);
        static evalCode : &'static [Instruction] = &[Eval];
        self.execute(&mut stack, evalCode);
        assert_eq!(stack.len(), 1);
        stack[0].borrow().clone()
    }

    fn execute(&'a self, stack : &mut ~[Rc<Node<'a>>], code : &[Instruction]) {
        debug!("----------------------------");
        debug!("Entering frame with stack");
        for x in stack.iter() {
            debug!("{:?}", x.borrow());
        }
        debug!("");
        let mut i = 0;
        while i < code.len() {
            debug!("Executing instruction : {:?}", code[i]);
            match &code[i] {
                &Add => primitive(stack, |l, r| { l + r }),
                &Sub => primitive(stack, |l, r| { l - r }),
                &Multiply => primitive(stack, |l, r| { l * r }),
                &Divide => primitive(stack, |l, r| { l / r }),
                &Remainder => primitive(stack, |l, r| { l % r }),
                &PushInt(value) => { stack.push(Rc::new(Int(value))); }
                &Push(index) => {
                    let x = stack[index].clone();
                    debug!("Pushed {:?}", x.borrow());
                    for j in range(0, stack.len()) {
                        debug!(" {}  {:?}", j, stack[j].borrow());
                    }
                    stack.push(x);
                }
                &PushGlobal(index) => {
                    match &self.assembly.superCombinators[index] {
                        &(_, ref sc) => stack.push(Rc::new(Combinator(sc)))
                    }
                }
                &Mkap => {
                    let func = stack.pop();
                    let arg = stack.pop();
                    debug!("Mkap {:?} {:?}", func.borrow(), arg.borrow());
                    stack.push(Rc::new(Application(func, arg)));
                }
                &Eval => {
                    static unwindCode : &'static [Instruction] = &[Unwind];
                    let mut newStack = ~[stack.pop()];
                    self.execute(&mut newStack, unwindCode);
                    assert_eq!(newStack.len(), 1);
                    stack.push(newStack.pop());
                }
                &Pop(num) => {
                    for _ in range(0, num) {
                        stack.pop();
                    }
                }
                &Update(index) => {
                    stack[index] = Rc::new(Indirection(stack[stack.len() - 1].clone()));
                }
                &Unwind => {
                    match (*stack[stack.len() - 1].borrow()).clone() {
                        Application(func, _) => {
                            stack.push(func);
                            i -= 1;//Redo the unwind instruction
                        }
                        Combinator(comb) => {
                            if stack.len() - 1 < comb.arity as uint {
                                while stack.len() > 1 {
                                    stack.pop();
                                }
                            }
                            else {
                                for j in range(stack.len() - (comb.arity as uint) - 1, stack.len() - 1) {
                                    stack[j] = match stack[j].borrow() {
                                        &Application(_, ref arg) => arg.clone(),
                                        _ => fail!("Expected Application")
                                    };
                                }
                                let mut newStack = ~[];
                                for i in range(0, comb.arity as uint) {
                                    let index = stack.len() - i - 2;
                                    newStack.push(stack[index].clone());
                                }

                                debug!("Call");
                                for j in range(0, newStack.len()) {
                                    debug!(" {}  {:?}", j, newStack[j].borrow());
                                }
                                self.execute(&mut newStack, comb.instructions);
                                assert_eq!(newStack.len(), 1);
                                for _ in range(0, comb.arity + 1) {
                                    stack.pop();
                                }
                                stack.push(newStack.pop());
                            }
                        }
                        Indirection(node) => {
                            stack[stack.len() - 1] = node;
                            i -= 1;
                        }
                        _ => ()
                    }
                }
                &Slide(size) => {
                    let top = stack.pop();
                    for _ in range(0, size) {
                        stack.pop();
                    }
                    stack.push(top);
                }
                &Split(_) => {
                    let x = stack.pop();
                    match x.borrow() {
                        &Constructor(_, ref fields) => {
                            for field in fields.iter() {
                                stack.push(field.clone());
                            }
                        }
                        _ => fail!("Expected constructor in Split instruction")
                    }
                }
                &Pack(tag, arity) => {
                    let args = std::vec::from_fn(arity as uint, |_| stack.pop());
                    stack.push(Rc::new(Constructor(tag, args)));
                }
                &CaseJump(jump_tag) => {
                    match stack[stack.len() - 1].borrow() {
                        &Constructor(tag, _) => {
                            if jump_tag != tag as uint {
                                i += 1;//Skip the jump instruction
                            }
                        }
                        _ => fail!("Expected constructor when executing CaseJump")
                    }
                }
                &Jump(to) => {
                    i = to - 1;
                }
                //undefined => fail!("Use of undefined instruction {:?}", undefined)
            }
            i += 1;
        }
        debug!("End frame");
        debug!("--------------------------");
    }
}

fn primitive(stack: &mut ~[Rc<Node>], f: |int, int| -> int) {
    let r = stack.pop();
    let l = stack.pop();
    match (l.borrow(), r.borrow()) {
        (&Int(lhs), &Int(rhs)) => stack.push(Rc::new(Int(f(lhs, rhs)))),
        (lhs, rhs) => fail!("Expected fully evaluted numbers in primitive instruction\n LHS: {:?}\nRHS: {:?} ", lhs, rhs)
    }
}

fn main() {
    let arguments = std::os::args();
    match arguments {
        [_, expr_str] => {
            let mut parser = Parser::new(expr_str.chars());
            let mut expr = parser.expression_();

            let mut type_env = TypeEnvironment::new();
            type_env.typecheck(&mut expr);

            let mut compiler = Compiler::new();
            let instr = compiler.compileExpression(&expr);

            let vm = VM::new();
            let mut stack = ~[];
            vm.execute(&mut stack, instr);
            println!("{:?}", stack[0].borrow());
        }
        [_, ~"-l", filename] => {
            let path = &Path::new(filename);
            let s  = File::open(path).read_to_end();
            let contents : &str = from_utf8(s);
            let result = execute_main(contents.chars());
            match result {
                Some(x) => println!("{:?}", x),
                None => println!("Error running file {:?}", path)
            }
        }
        _ => return println!("Expected one argument which is the expression or 2 arguments where the first is -l and the second the file to run (needs a main function)")
    }
}

#[deriving(Eq)]
enum VMResult {
    IntResult(int),
    ConstructorResult(u16, ~[VMResult])
}

fn compile_iter<T : Iterator<char>>(iterator: T) -> Assembly {
    let mut parser = Parser::new(iterator);
    let mut module = parser.module();

    let mut typer = TypeEnvironment::new();
    typer.typecheck_module(&mut module);

    let mut compiler = Compiler::new();
    compiler.compileModule(&module)
}

fn extract_result(node: Node) -> Option<VMResult> {
    match node {
        Constructor(tag, fields) => {
            let mut result = ~[];
            for field in fields.iter() {
                match extract_result(field.borrow().clone()) {
                    Some(x) => result.push(x),
                    None => return None
                }
            }
            Some(ConstructorResult(tag, result))
        }
        Int(i) => Some(IntResult(i)),
        x => {
            println!("Can't evalute result to {:?}", x);
            None
        }
    }
}

fn execute_main<T : Iterator<char>>(iterator: T) -> Option<VMResult> {
    let mut vm = VM::new();
    vm.assembly = compile_iter(iterator);
    let x = vm.assembly.superCombinators.iter().find(|& &(ref name, _)| *name == ~"main");
    match x {
        Some(&(_, ref sc)) => {
            assert!(sc.arity == 0);
            let result = vm.evaluate(sc.instructions);
            extract_result(result)
        }
        None => None
    }
}

#[test]
fn test_primitive()
{
    assert_eq!(execute_main("main = primIntAdd 10 5".chars()), Some(IntResult(15)));
    assert_eq!(execute_main("main = primIntSubtract 7 (primIntMultiply 2 3)".chars()), Some(IntResult(1)));
    assert_eq!(execute_main("main = primIntDivide 10 (primIntRemainder 6 4)".chars()), Some(IntResult(5)));
}

#[test]
fn test_function()
{
    let module =
r"mult2 x = primIntMultiply x 2

main = mult2 10";
    assert_eq!(execute_main(module.chars()), Some(IntResult(20)));

    let module2 =
r"mult2 x = primIntMultiply x 2

add x y = primIntAdd y x

main = add 3 (mult2 10)";
    assert_eq!(execute_main(module2.chars()), Some(IntResult(23)));
}
#[test]
fn test_case()
{
    let module =
r"mult2 x = primIntMultiply x 2

main = case [mult2 123, 0] of
    : x xs -> x
    [] -> 10";
    assert_eq!(execute_main(module.chars()), Some(IntResult(246)));
}

#[test]
fn test_data_types()
{
    let module =
r"data Bool = True | False

test = False

main = case test of
    False -> 0
    True -> 1";
    assert_eq!(execute_main(module.chars()), Some(IntResult(0)));
}
<|endoftext|>


<commit_before>fn main() {
   println!("yo wassup world!");
}<commit_msg>235 problem in rust<commit_after>use std::collections::BinaryHeap;

// Prints out numbers whose only prime factors are 2, 3, and 5.
fn main() {
    let mut heap = BinaryHeap::new();
    heap.push(-1);

    let mut last = 0;
    loop {
        let i = heap.pop();
        let x = match i {
            Some(n) => -n,
            None => 0,
        };
        if x > last {
            println!("{}", x);
            last = x;
            heap.push(-2 * x);
            heap.push(-3 * x);
            heap.push(-5 * x);
        }
    }
}
<|endoftext|>


<commit_before>
extern mod syntax;
extern mod rustc;
extern mod extra;
use rustc::{front, metadata, driver, middle};

use syntax::parse;
use syntax::ast;
use syntax::ast_map;
use syntax::visit;
use syntax::visit::*;
use syntax::visit::{Visitor, fn_kind};
use find_ast_node::*;
use text_formatting::*;

use syntax::abi::AbiSet;
use syntax::ast;
use syntax::codemap::span;

use std::os;
use std::local_data;
use extra::json::ToJson;

mod text_formatting;
mod find_ast_node;

pub static ctxtkey: local_data::Key<@DocContext> = &local_data::Key;

pub macro_rules! logi{
	($($a:expr),*)=>(println((file!()+":"+line!().to_str()+": " $(+$a.to_str())*) .indent(2,160)))
}
//macro_rules! dump{ ($a:expr)=>(logi!(fmt!("%s=%?",stringify!($a),$a).indent(2,160));)}
macro_rules! dump{ ($($a:expr),*)=>
	(	{	let mut txt=~"";
			$( { txt=txt.append(
				 fmt!("%s=%?",stringify!($a),$a)+",")
				}
			);*;
			logi!(txt);
		}
	)
}

struct DocContext {
    crate: @ast::crate,
    tycx: middle::ty::ctxt,
    sess: driver::session::Session
}

/// tags: crate,ast,parse resolve
/// Parses, resolves the given crate
fn get_ast_and_resolve(cpath: &Path, libs: ~[Path]) -> DocContext {

    let parsesess = parse::new_parse_sess(None);
    let sessopts = @driver::session::options {
        binary: @"rustdoc",
        maybe_sysroot: Some(@std::os::self_exe_path().get().pop()),
        addl_lib_search_paths: @mut libs,
        .. copy (*rustc::driver::session::basic_options())
    };

    let diagnostic_handler = syntax::diagnostic::mk_handler(None);
    let span_diagnostic_handler =
        syntax::diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);

    let mut sess = driver::driver::build_session_(sessopts, parsesess.cm,
                                                  syntax::diagnostic::emit,
                                                  span_diagnostic_handler);

    let (crate, tycx) = driver::driver::compile_upto(sess, sessopts.cfg.clone(),
                                                     &driver::driver::file_input(cpath.clone()),
                                                     driver::driver::cu_typeck, None);

	let c=crate.unwrap();
	let t=tycx.unwrap();
    DocContext { crate: c, tycx: t, sess: sess }
}
struct Foo {
	i:int,j:int
}

// CALLING C++ FROM RUST
// =====================
//
// manually rolled vtables for C++.
// For each virtual method, create a pointer member.
// create wrapper functions that invoke the vtable and
//

fn main() {
    use extra::getopts::*;
    use std::hashmap::HashMap;

    let args = os::args();

    let opts = ~[
        optmulti("L")
    ];

    let matches = getopts(args.tail(), opts).get();
    let libs = opt_strs(&matches, "L").map(|s| Path(*s));
	dump!(args,matches);
	dump!(libs);
    let ctxt = @get_ast_and_resolve(&Path(matches.free[0]), libs);

	// TODO: parse commandline source locations,convert to codemap locations
	//dump!(ctxt.tycx);

    local_data::set(ctxtkey, ctxt);
	logi!("")
	logi!("==== Test node search by location...===")
	dump!(find_ast_node::find(ctxt.crate,25))
	dump!(find_ast_node::find(ctxt.crate,97))

	let mut pos=15 as uint;
	while pos<300 {
		// get the AST node under 'pos', and dump info
		logi!(~"Find AST node at:",pos)
		let node = find_ast_node::find(ctxt.crate,pos);
		let node_info = get_node_info_str(ctxt,node);
		dump!(node_info);
		// TODO - get infered type from ctxt.node_types??
		// node_id = get_node_id()
		// node_type=ctxt.node_types./*node_type_table*/.get...

		pos+=10;
	}
	//dump_ctxt_table(ctxt:DocContext)
}

fn get_node_info_str(ctxt:&DocContext,node:&[find_ast_node::AstNode])->~str
{
	fn path_to_str(ctxt:&DocContext, path:&ast::Path)->~str
	{
		let mut acc=~"";
		for path.idents.iter().advance |x|{
			acc=acc.append(ctxt.sess.str_of(*x))+"."
		}
		acc
		// typeparams too... path.types?
	}

	match node.last() {
//			TODO -factor out repeatedly used functions here..
//			fn astnode_pat_to_str(&astnode_pat(x))->~str
//			fn path_to_str(&astnode_pat(x))->~str
//			fn expr_to_str(&astnode_pat(x))->~str

		&astnode_view_item(x)=>~"view_item: ?",
		&astnode_item(x)=>~"item: "+ctxt.sess.str_of(x.ident)+
			match x.node {
				ast::item_fn(ref fn_decl,_,_,_,_) =>~" fn_decl",
				ast::item_struct(ref struct_def,_) =>~" struct_def",
				_=>~"item_unknown"
			},

		&astnode_local(x)=>~"local: ?",
		&astnode_block(x)=>~"block: ?",
		&astnode_stmt(x)=>~"stmt: ?",
		&astnode_arm(x)=>~"arm: ?",
		&astnode_struct_field(sf)=>
			match(sf.node.kind){
				ast::named_field(nf,vis)=>"struct named_field: "+ctxt.sess.str_of(nf)+" ",
				_=>~"struct anon_field"
			},
		&astnode_pat(x)=>~"pattern: "+
			// todo -factor out and recurse
			match x.node{
				ast::pat_ident(bind_mode,ref path, opt)=>~"pat_ident:"+path_to_str(ctxt,path),
				ast::pat_enum(ref path,ref efields)=>~"pat_enum:"+path_to_str(ctxt,path),//todo-fields..
				ast::pat_struct(ref path,ref sfields,b)=>~"pat_struct:"+path_to_str(ctxt,path),
				ast::pat_tup(ref elems)=>~"pat_tupl:",//+elems.map(|x|get_pat_info(ctxt,x)),
				ast::pat_box(ref box)=>~"box",
				ast::pat_uniq(ref u)=>~"uniq",
				ast::pat_region(ref p)=>~"rgn",
				ast::pat_lit(ref e)=>~"literal",
				ast::pat_range(ref e_start,ref e_end)=>~"range",

				_=>~"?"
			}
		,
		&astnode_decl(x)=>~"decl: ?",
		&astnode_ty(x)=>~"type: "+
			match x.node{
				ast::ty_nil=> ~"nil",
				ast::ty_bot=>~"bottomtype",
				ast::ty_box(ref mt)=>~"box",
				ast::ty_vec(ref mt)=>~"vec",
				ast::ty_fixed_length_vec(ref mt,ref expr)=>~"[T,..N]",
				ast::ty_ptr(ref mt)=>~"ptr",
				ast::ty_rptr(ref lifetime,ref mt)=>~"rptr",
				ast::ty_tup(ref types)=>~"tuple[..]", //todo: factor this out, map..
				ast::ty_path(ref path,ref params,node_id)=>~"path:"+path_to_str(ctxt,path)
				,

				ast::ty_infer=>~"infered",
				_ =>~"?"
			}
		,
		&astnode_struct_def(sf)=>~"struct def",
		_=>	~"unknown"
	}
}

fn dump_ctxt_table(ctxt:DocContext) {
	logi!("===Test ctxt symbol table..===")
	for ctxt.tycx.def_map.iter().advance |(key,value)|{
		dump!(key,value);
	}
}

<commit_msg>node id debug<commit_after>
extern mod syntax;
extern mod rustc;
extern mod extra;
use rustc::{front, metadata, driver, middle};

use syntax::parse;
use syntax::ast;
use syntax::ast_map;
use syntax::visit;
use syntax::visit::*;
use syntax::visit::{Visitor, fn_kind};
use find_ast_node::*;
use text_formatting::*;

use syntax::abi::AbiSet;
use syntax::ast;
use syntax::codemap::span;

use std::os;
use std::local_data;
use extra::json::ToJson;

mod text_formatting;
mod find_ast_node;

pub static ctxtkey: local_data::Key<@DocContext> = &local_data::Key;

pub macro_rules! logi{
	($($a:expr),*)=>(println((file!()+":"+line!().to_str()+": " $(+$a.to_str())*) .indent(2,160)))
}
//macro_rules! dump{ ($a:expr)=>(logi!(fmt!("%s=%?",stringify!($a),$a).indent(2,160));)}
macro_rules! dump{ ($($a:expr),*)=>
	(	{	let mut txt=~"";
			$( { txt=txt.append(
				 fmt!("%s=%?",stringify!($a),$a)+",")
				}
			);*;
			logi!(txt);
		}
	)
}

struct DocContext {
    crate: @ast::crate,
    tycx: middle::ty::ctxt,
    sess: driver::session::Session
}

/// tags: crate,ast,parse resolve
/// Parses, resolves the given crate
fn get_ast_and_resolve(cpath: &Path, libs: ~[Path]) -> DocContext {

    let parsesess = parse::new_parse_sess(None);
    let sessopts = @driver::session::options {
        binary: @"rustdoc",
        maybe_sysroot: Some(@std::os::self_exe_path().get().pop()),
        addl_lib_search_paths: @mut libs,
        .. copy (*rustc::driver::session::basic_options())
    };

    let diagnostic_handler = syntax::diagnostic::mk_handler(None);
    let span_diagnostic_handler =
        syntax::diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);

    let mut sess = driver::driver::build_session_(sessopts, parsesess.cm,
                                                  syntax::diagnostic::emit,
                                                  span_diagnostic_handler);

    let (crate, tycx) = driver::driver::compile_upto(sess, sessopts.cfg.clone(),
                                                     &driver::driver::file_input(cpath.clone()),
                                                     driver::driver::cu_typeck, None);

	let c=crate.unwrap();
	let t=tycx.unwrap();
    DocContext { crate: c, tycx: t, sess: sess }
}
struct Foo {
	i:int,j:int
}

// CALLING C++ FROM RUST
// =====================
//
// manually rolled vtables for C++.
// For each virtual method, create a pointer member.
// create wrapper functions that invoke the vtable and
//

fn main() {
    use extra::getopts::*;
    use std::hashmap::HashMap;

    let args = os::args();

    let opts = ~[
        optmulti("L")
    ];

    let matches = getopts(args.tail(), opts).get();
    let libs = opt_strs(&matches, "L").map(|s| Path(*s));
	dump!(args,matches);
	dump!(libs);
    let ctxt = @get_ast_and_resolve(&Path(matches.free[0]), libs);

	// TODO: parse commandline source locations,convert to codemap locations
	//dump!(ctxt.tycx);

	logi!("==== dump def table.===")
	dump_ctxt_table(ctxt);

    local_data::set(ctxtkey, ctxt);
	logi!("")
	logi!("==== Test node search by location...===")

	let mut pos=15 as uint;
	while pos<250 {
		// get the AST node under 'pos', and dump info
		logi!(~"Find AST node at:",pos)
		let node = find_ast_node::find(ctxt.crate,pos);
		let node_info = get_node_info_str(ctxt,node);
		dump!(node_info);
		// TODO - get infered type from ctxt.node_types??
		// node_id = get_node_id()
		// node_type=ctxt.node_types./*node_type_table*/.get...

		pos+=12;
	}
}

fn get_node_info_str(ctxt:&DocContext,node:&[find_ast_node::AstNode])->~str
{
	fn path_to_str(ctxt:&DocContext, path:&ast::Path)->~str
	{
		let mut acc=~"";
		for path.idents.iter().advance |x|{
			acc=acc.append(ctxt.sess.str_of(*x))+"."
		}
		acc
		// typeparams too... path.types?
	}
	match node.last() {
//			TODO -factor out repeatedly used functions here..
//			fn astnode_pat_to_str(&astnode_pat(x))->~str
//			fn path_to_str(&astnode_pat(x))->~str
//			fn expr_to_str(&astnode_pat(x))->~str

		&astnode_view_item(x)=>~"view_item: ?",
		&astnode_item(x)=>~"item: "+
			~"id="+x.id.to_str()+~" "+
			ctxt.sess.str_of(x.ident)+
			match x.node {
				ast::item_fn(ref fn_decl,_,_,_,_) =>~" fn_decl",
				ast::item_struct(ref struct_def,_) =>~" struct_def",
				_=>~"item_unknown"
			},

		&astnode_local(x)=>~"local: ?",
		&astnode_block(x)=>~"block: ?",
		&astnode_stmt(x)=>~"stmt: ?",
		&astnode_arm(x)=>~"arm: ?",
		&astnode_struct_field(sf)=>
			~"id="+sf.node.id.to_str()+~" "+
			match(sf.node.kind){
				ast::named_field(nf,vis)=>"struct named_field: "+ctxt.sess.str_of(nf)+" ",
				_=>~"struct anon_field"
			},
		&astnode_pat(x)=>~"pattern: "+
			~"id="+x.id.to_str()+~" "+
			// todo -factor out and recurse
			match x.node{
				ast::pat_ident(bind_mode,ref path, opt)=>~"pat_ident:"+path_to_str(ctxt,path),
				ast::pat_enum(ref path,ref efields)=>~"pat_enum:"+path_to_str(ctxt,path),//todo-fields..
				ast::pat_struct(ref path,ref sfields,b)=>~"pat_struct:"+path_to_str(ctxt,path),
				ast::pat_tup(ref elems)=>~"pat_tupl:",//+elems.map(|x|get_pat_info(ctxt,x)),
				ast::pat_box(ref box)=>~"box",
				ast::pat_uniq(ref u)=>~"uniq",
				ast::pat_region(ref p)=>~"rgn",
				ast::pat_lit(ref e)=>~"literal",
				ast::pat_range(ref e_start,ref e_end)=>~"range",

				_=>~"?"
			}
		,
		&astnode_decl(x)=>~"decl: ?",
		&astnode_ty(x)=>~"type: "+
//			~"id="+x.node.id.to_str()+~" "+
			match x.node{
				ast::ty_nil=> ~"nil",
				ast::ty_bot=>~"bottomtype",
				ast::ty_box(ref mt)=>~"box",
				ast::ty_vec(ref mt)=>~"vec",
				ast::ty_fixed_length_vec(ref mt,ref expr)=>~"[T,..N]",
				ast::ty_ptr(ref mt)=>~"ptr",
				ast::ty_rptr(ref lifetime,ref mt)=>~"rptr",
				ast::ty_tup(ref types)=>~"tuple[..]", //todo: factor this out, map..
				ast::ty_path(ref path,ref params,node_id)=>~"path:id="+node_id.to_str()+" "+path_to_str(ctxt,path)
				,

				ast::ty_infer=>~"infered",
				_ =>~"?"
			}
		,
		&astnode_struct_def(sf)=>~"struct def",
		_=>	~"unknown"
	}
}
// see: tycx.node_types:node_type_table:HashMap<id,t>
// 't'=opaque ptr, ty::get(:t)->t_box_ to resolve it

fn dump_ctxt_table(ctxt:&DocContext) {
//	let a:()=ctxt.tycx.node_types
	logi!("===Test ctxt def-map table..===");
	for ctxt.tycx.def_map.iter().advance |(key,value)|{
		dump!(key,value);
	}
}

<|endoftext|>


<commit_before>mod generated;

use hir::Semantics;
use ide_db::{
    base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt},
    helpers::{
        insert_use::{InsertUseConfig, MergeBehavior},
        SnippetCap,
    },
    source_change::FileSystemEdit,
    RootDatabase,
};
use syntax::TextRange;
use test_utils::{assert_eq_text, extract_offset, extract_range};

use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists};
use stdx::{format_to, trim_indent};

pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
    snippet_cap: SnippetCap::new(true),
    allowed: None,
    insert_use: InsertUseConfig {
        merge: Some(MergeBehavior::Full),
        prefix_kind: hir::PrefixKind::Plain,
    },
};

pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
    RootDatabase::with_single_file(text)
}

pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_after: &str) {
    let ra_fixture_after = trim_indent(ra_fixture_after);
    check(assist, ra_fixture_before, ExpectedResult::After(&ra_fixture_after), None);
}

// There is no way to choose what assist within a group you want to test against,
// so this is here to allow you choose.
pub(crate) fn check_assist_by_label(
    assist: Handler,
    ra_fixture_before: &str,
    ra_fixture_after: &str,
    label: &str,
) {
    let ra_fixture_after = trim_indent(ra_fixture_after);
    check(assist, ra_fixture_before, ExpectedResult::After(&ra_fixture_after), Some(label));
}

// FIXME: instead of having a separate function here, maybe use
// `extract_ranges` and mark the target as `<target> </target>` in the
// fixture?
pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) {
    check(assist, ra_fixture, ExpectedResult::Target(target), None);
}

pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) {
    check(assist, ra_fixture, ExpectedResult::NotApplicable, None);
}

fn check_doc_test(assist_id: &str, before: &str, after: &str) {
    let after = trim_indent(after);
    let (db, file_id, selection) = RootDatabase::with_range_or_offset(&before);
    let before = db.file_text(file_id).to_string();
    let frange = FileRange { file_id, range: selection.into() };

    let assist = Assist::get(&db, &TEST_CONFIG, true, frange)
        .into_iter()
        .find(|assist| assist.id.0 == assist_id)
        .unwrap_or_else(|| {
            panic!(
                "\n\nAssist is not applicable: {}\nAvailable assists: {}",
                assist_id,
                Assist::get(&db, &TEST_CONFIG, false, frange)
                    .into_iter()
                    .map(|assist| assist.id.0)
                    .collect::<Vec<_>>()
                    .join(", ")
            )
        });

    let actual = {
        let source_change = assist.source_change.unwrap();
        let mut actual = before;
        if let Some(source_file_edit) = source_change.get_source_edit(file_id) {
            source_file_edit.apply(&mut actual);
        }
        actual
    };
    assert_eq_text!(&after, &actual);
}

enum ExpectedResult<'a> {
    NotApplicable,
    After(&'a str),
    Target(&'a str),
}

fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: Option<&str>) {
    let (db, file_with_caret_id, range_or_offset) = RootDatabase::with_range_or_offset(before);
    let text_without_caret = db.file_text(file_with_caret_id).to_string();

    let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() };

    let sema = Semantics::new(&db);
    let config = TEST_CONFIG;
    let ctx = AssistContext::new(sema, &config, frange);
    let mut acc = Assists::new(&ctx, true);
    handler(&mut acc, &ctx);
    let mut res = acc.finish();

    let assist = match assist_label {
        Some(label) => res.into_iter().find(|resolved| resolved.label == label),
        None => res.pop(),
    };

    match (assist, expected) {
        (Some(assist), ExpectedResult::After(after)) => {
            let source_change = assist.source_change.unwrap();
            assert!(!source_change.source_file_edits.is_empty());
            let skip_header = source_change.source_file_edits.len() == 1
                && source_change.file_system_edits.len() == 0;

            let mut buf = String::new();
            for (file_id, edit) in source_change.source_file_edits {
                let mut text = db.file_text(file_id).as_ref().to_owned();
                edit.apply(&mut text);
                if !skip_header {
                    let sr = db.file_source_root(file_id);
                    let sr = db.source_root(sr);
                    let path = sr.path_for_file(&file_id).unwrap();
                    format_to!(buf, "//- {}\n", path)
                }
                buf.push_str(&text);
            }

            for file_system_edit in source_change.file_system_edits {
                if let FileSystemEdit::CreateFile { dst, initial_contents } = file_system_edit {
                    let sr = db.file_source_root(dst.anchor);
                    let sr = db.source_root(sr);
                    let mut base = sr.path_for_file(&dst.anchor).unwrap().clone();
                    base.pop();
                    let created_file_path = format!("{}{}", base.to_string(), &dst.path[1..]);
                    format_to!(buf, "//- {}\n", created_file_path);
                    buf.push_str(&initial_contents);
                }
            }

            assert_eq_text!(after, &buf);
        }
        (Some(assist), ExpectedResult::Target(target)) => {
            let range = assist.target;
            assert_eq_text!(&text_without_caret[range], target);
        }
        (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"),
        (None, ExpectedResult::After(_)) | (None, ExpectedResult::Target(_)) => {
            panic!("code action is not applicable")
        }
        (None, ExpectedResult::NotApplicable) => (),
    };
}

#[test]
fn assist_order_field_struct() {
    let before = "struct Foo { $0bar: u32 }";
    let (before_cursor_pos, before) = extract_offset(before);
    let (db, file_id) = with_single_file(&before);
    let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
    let assists = Assist::get(&db, &TEST_CONFIG, false, frange);
    let mut assists = assists.iter();

    assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)");
    assert_eq!(assists.next().expect("expected assist").label, "Add `#[derive]`");
}

#[test]
fn assist_order_if_expr() {
    let before = "
    pub fn test_some_range(a: int) -> bool {
        if let 2..6 = $05$0 {
            true
        } else {
            false
        }
    }";
    let (range, before) = extract_range(before);
    let (db, file_id) = with_single_file(&before);
    let frange = FileRange { file_id, range };
    let assists = Assist::get(&db, &TEST_CONFIG, false, frange);
    let mut assists = assists.iter();

    assert_eq!(assists.next().expect("expected assist").label, "Extract into variable");
    assert_eq!(assists.next().expect("expected assist").label, "Replace with match");
}

#[test]
fn assist_filter_works() {
    let before = "
    pub fn test_some_range(a: int) -> bool {
        if let 2..6 = $05$0 {
            true
        } else {
            false
        }
    }";
    let (range, before) = extract_range(before);
    let (db, file_id) = with_single_file(&before);
    let frange = FileRange { file_id, range };

    {
        let mut cfg = TEST_CONFIG;
        cfg.allowed = Some(vec![AssistKind::Refactor]);

        let assists = Assist::get(&db, &cfg, false, frange);
        let mut assists = assists.iter();

        assert_eq!(assists.next().expect("expected assist").label, "Extract into variable");
        assert_eq!(assists.next().expect("expected assist").label, "Replace with match");
    }

    {
        let mut cfg = TEST_CONFIG;
        cfg.allowed = Some(vec![AssistKind::RefactorExtract]);
        let assists = Assist::get(&db, &cfg, false, frange);
        assert_eq!(assists.len(), 1);

        let mut assists = assists.iter();
        assert_eq!(assists.next().expect("expected assist").label, "Extract into variable");
    }

    {
        let mut cfg = TEST_CONFIG;
        cfg.allowed = Some(vec![AssistKind::QuickFix]);
        let assists = Assist::get(&db, &cfg, false, frange);
        assert!(assists.is_empty(), "All asserts but quickfixes should be filtered out");
    }
}
<commit_msg>Add #[track_caller] to assist tests<commit_after>mod generated;

use hir::Semantics;
use ide_db::{
    base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt},
    helpers::{
        insert_use::{InsertUseConfig, MergeBehavior},
        SnippetCap,
    },
    source_change::FileSystemEdit,
    RootDatabase,
};
use syntax::TextRange;
use test_utils::{assert_eq_text, extract_offset, extract_range};

use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists};
use stdx::{format_to, trim_indent};

pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
    snippet_cap: SnippetCap::new(true),
    allowed: None,
    insert_use: InsertUseConfig {
        merge: Some(MergeBehavior::Full),
        prefix_kind: hir::PrefixKind::Plain,
    },
};

pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
    RootDatabase::with_single_file(text)
}

pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_after: &str) {
    let ra_fixture_after = trim_indent(ra_fixture_after);
    check(assist, ra_fixture_before, ExpectedResult::After(&ra_fixture_after), None);
}

// There is no way to choose what assist within a group you want to test against,
// so this is here to allow you choose.
pub(crate) fn check_assist_by_label(
    assist: Handler,
    ra_fixture_before: &str,
    ra_fixture_after: &str,
    label: &str,
) {
    let ra_fixture_after = trim_indent(ra_fixture_after);
    check(assist, ra_fixture_before, ExpectedResult::After(&ra_fixture_after), Some(label));
}

// FIXME: instead of having a separate function here, maybe use
// `extract_ranges` and mark the target as `<target> </target>` in the
// fixture?
#[track_caller]
pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) {
    check(assist, ra_fixture, ExpectedResult::Target(target), None);
}

#[track_caller]
pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) {
    check(assist, ra_fixture, ExpectedResult::NotApplicable, None);
}

#[track_caller]
fn check_doc_test(assist_id: &str, before: &str, after: &str) {
    let after = trim_indent(after);
    let (db, file_id, selection) = RootDatabase::with_range_or_offset(&before);
    let before = db.file_text(file_id).to_string();
    let frange = FileRange { file_id, range: selection.into() };

    let assist = Assist::get(&db, &TEST_CONFIG, true, frange)
        .into_iter()
        .find(|assist| assist.id.0 == assist_id)
        .unwrap_or_else(|| {
            panic!(
                "\n\nAssist is not applicable: {}\nAvailable assists: {}",
                assist_id,
                Assist::get(&db, &TEST_CONFIG, false, frange)
                    .into_iter()
                    .map(|assist| assist.id.0)
                    .collect::<Vec<_>>()
                    .join(", ")
            )
        });

    let actual = {
        let source_change = assist.source_change.unwrap();
        let mut actual = before;
        if let Some(source_file_edit) = source_change.get_source_edit(file_id) {
            source_file_edit.apply(&mut actual);
        }
        actual
    };
    assert_eq_text!(&after, &actual);
}

enum ExpectedResult<'a> {
    NotApplicable,
    After(&'a str),
    Target(&'a str),
}

#[track_caller]
fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label: Option<&str>) {
    let (db, file_with_caret_id, range_or_offset) = RootDatabase::with_range_or_offset(before);
    let text_without_caret = db.file_text(file_with_caret_id).to_string();

    let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() };

    let sema = Semantics::new(&db);
    let config = TEST_CONFIG;
    let ctx = AssistContext::new(sema, &config, frange);
    let mut acc = Assists::new(&ctx, true);
    handler(&mut acc, &ctx);
    let mut res = acc.finish();

    let assist = match assist_label {
        Some(label) => res.into_iter().find(|resolved| resolved.label == label),
        None => res.pop(),
    };

    match (assist, expected) {
        (Some(assist), ExpectedResult::After(after)) => {
            let source_change = assist.source_change.unwrap();
            assert!(!source_change.source_file_edits.is_empty());
            let skip_header = source_change.source_file_edits.len() == 1
                && source_change.file_system_edits.len() == 0;

            let mut buf = String::new();
            for (file_id, edit) in source_change.source_file_edits {
                let mut text = db.file_text(file_id).as_ref().to_owned();
                edit.apply(&mut text);
                if !skip_header {
                    let sr = db.file_source_root(file_id);
                    let sr = db.source_root(sr);
                    let path = sr.path_for_file(&file_id).unwrap();
                    format_to!(buf, "//- {}\n", path)
                }
                buf.push_str(&text);
            }

            for file_system_edit in source_change.file_system_edits {
                if let FileSystemEdit::CreateFile { dst, initial_contents } = file_system_edit {
                    let sr = db.file_source_root(dst.anchor);
                    let sr = db.source_root(sr);
                    let mut base = sr.path_for_file(&dst.anchor).unwrap().clone();
                    base.pop();
                    let created_file_path = format!("{}{}", base.to_string(), &dst.path[1..]);
                    format_to!(buf, "//- {}\n", created_file_path);
                    buf.push_str(&initial_contents);
                }
            }

            assert_eq_text!(after, &buf);
        }
        (Some(assist), ExpectedResult::Target(target)) => {
            let range = assist.target;
            assert_eq_text!(&text_without_caret[range], target);
        }
        (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"),
        (None, ExpectedResult::After(_)) | (None, ExpectedResult::Target(_)) => {
            panic!("code action is not applicable")
        }
        (None, ExpectedResult::NotApplicable) => (),
    };
}

#[test]
fn assist_order_field_struct() {
    let before = "struct Foo { $0bar: u32 }";
    let (before_cursor_pos, before) = extract_offset(before);
    let (db, file_id) = with_single_file(&before);
    let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
    let assists = Assist::get(&db, &TEST_CONFIG, false, frange);
    let mut assists = assists.iter();

    assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)");
    assert_eq!(assists.next().expect("expected assist").label, "Add `#[derive]`");
}

#[test]
fn assist_order_if_expr() {
    let before = "
    pub fn test_some_range(a: int) -> bool {
        if let 2..6 = $05$0 {
            true
        } else {
            false
        }
    }";
    let (range, before) = extract_range(before);
    let (db, file_id) = with_single_file(&before);
    let frange = FileRange { file_id, range };
    let assists = Assist::get(&db, &TEST_CONFIG, false, frange);
    let mut assists = assists.iter();

    assert_eq!(assists.next().expect("expected assist").label, "Extract into variable");
    assert_eq!(assists.next().expect("expected assist").label, "Replace with match");
}

#[test]
fn assist_filter_works() {
    let before = "
    pub fn test_some_range(a: int) -> bool {
        if let 2..6 = $05$0 {
            true
        } else {
            false
        }
    }";
    let (range, before) = extract_range(before);
    let (db, file_id) = with_single_file(&before);
    let frange = FileRange { file_id, range };

    {
        let mut cfg = TEST_CONFIG;
        cfg.allowed = Some(vec![AssistKind::Refactor]);

        let assists = Assist::get(&db, &cfg, false, frange);
        let mut assists = assists.iter();

        assert_eq!(assists.next().expect("expected assist").label, "Extract into variable");
        assert_eq!(assists.next().expect("expected assist").label, "Replace with match");
    }

    {
        let mut cfg = TEST_CONFIG;
        cfg.allowed = Some(vec![AssistKind::RefactorExtract]);
        let assists = Assist::get(&db, &cfg, false, frange);
        assert_eq!(assists.len(), 1);

        let mut assists = assists.iter();
        assert_eq!(assists.next().expect("expected assist").label, "Extract into variable");
    }

    {
        let mut cfg = TEST_CONFIG;
        cfg.allowed = Some(vec![AssistKind::QuickFix]);
        let assists = Assist::get(&db, &cfg, false, frange);
        assert!(assists.is_empty(), "All asserts but quickfixes should be filtered out");
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;
extern crate cgmath;
extern crate rand;

use glium::{DisplayBuild, Surface};
use glium::glutin;
use cgmath::{EuclideanVector, Vector, Point};

#[derive(Copy, Clone)]
struct Vertex {
    position: (f32, f32, f32),
    tex_coords: (f32, f32),
}
implement_vertex!(Vertex, position, tex_coords);

#[derive(Copy, Clone)]
struct DrawId {
    draw_id: u32,
}
implement_vertex!(DrawId, draw_id);

struct Transform {
    transforms: [[[f32; 4]; 4]],
}
implement_buffer_content!(Transform);
implement_uniform_block!(Transform, transforms);

struct Textures<'a> {
    tex_address: [glium::texture::TextureHandle<'a>],
}
implement_buffer_content!(Textures<'a>);
implement_uniform_block!(Textures<'a>, tex_address);

const OBJECTS_X: usize = 100;
const OBJECTS_Y: usize = 100;
const OBJECTS_COUNT: usize = OBJECTS_X * OBJECTS_Y;

fn main() {
    let display = glutin::WindowBuilder::new()
                    .with_depth_buffer(24)
                    .build_glium()
                    .unwrap();

    let vertex_buffer = glium::VertexBuffer::new(&display, &[
        Vertex { position: (-0.5, -0.5, 0.0), tex_coords: (0.0,  0.0) },
        Vertex { position: ( 0.5, -0.5, 0.0), tex_coords: (0.0,  1.0) },
        Vertex { position: ( 0.5,  0.5, 0.0), tex_coords: (1.0,  0.0) },
        Vertex { position: (-0.5,  0.5, 0.0), tex_coords: (1.0,  1.0) },
    ]);

    let index_buffer = glium::index::IndexBuffer::new(&display,
        glium::index::PrimitiveType::TrianglesList,
        &[0, 1, 2, 0, 2, 3u16][..]
    );

    let program = program!(&display,
        410 => {
            vertex: include_str!("../textures_gl_bindless_multidraw_vs.glsl"),
            fragment: include_str!("../textures_gl_bindless_multidraw_fs.glsl"),
        }
    ).unwrap();

    let mut commands = glium::index::DrawCommandsIndicesBuffer::
                                  empty_dynamic_if_supported(&display, OBJECTS_COUNT * 3).unwrap();
    let mut transform_buffer = glium::uniforms::UniformBuffer::<Transform>::empty_unsized_if_supported(&display,
                                                                  16 * 4 * OBJECTS_COUNT).unwrap();

    let textures_storage = (0 .. OBJECTS_COUNT).map(|_| {
        let color1: (f32, f32, f32) = (rand::random(), rand::random(), rand::random());
        let color2: (f32, f32, f32) = (rand::random(), rand::random(), rand::random());
        let texture = glium::texture::Texture2d::new(&display, vec![vec![color1], vec![color2]]);
        texture.resident_if_supported().unwrap()
    }).collect::<Vec<_>>();

    let mut cb1 = glium::uniforms::UniformBuffer::<Textures>::empty_unsized_if_supported(&display, OBJECTS_COUNT * 8).unwrap();
    for (i, element) in cb1.map().tex_address.iter_mut().enumerate() {
        *element = glium::texture::TextureHandle::new(&textures_storage[i], &Default::default());
    }

    let mut iteration = 0;
    let mut buf_num = 0;

    loop {
        // writing the commands
        {
            let commands = commands.slice_mut(buf_num * OBJECTS_COUNT .. (buf_num + 1) * OBJECTS_COUNT).unwrap();
            let len = commands.len();
            let mut commands = commands.map_write();
            for i in 0 .. len {
                commands.set(i, glium::index::DrawCommandIndices {
                    count: index_buffer.len() as u32,
                    instance_count: 1,
                    first_index: 0,
                    base_vertex: 0,
                    base_instance: 0,
                });
            }
        }

        // writing the transforms
        {
            let angle = iteration as f32 * 0.01;
            iteration += 1;
            if angle > 2.0 * 3.141592 {
                iteration = 0;
            }

            let mut transforms = transform_buffer.map();
            let mut index = 0;

            for x in (0 .. OBJECTS_X) {
                for y in (0 .. OBJECTS_Y) {
                    let s = angle.sin();
                    let c = angle.cos();

                    let mut mat = [
                        [c,  -s,   0.0, 0.0],
                        [s,   c,   0.0, 0.0],
                        [0.0, 0.0, 1.0, 0.0],
                        [0.0, 0.0, 0.0, 1.0],
                    ];

                    mat[0][0] = 2.0 * (x as isize - OBJECTS_X as isize) as f32;
                    mat[3][1] = 2.0 * (y as isize - OBJECTS_Y as isize) as f32;
                    mat[3][2] = 0.0;

                    transforms.transforms[index] = mat;
                    index += 1;
                }
            }
        }

        let commands = commands.slice_mut(buf_num * OBJECTS_COUNT .. (buf_num + 1) * OBJECTS_COUNT).unwrap();
        let indices = glium::index::IndicesSource::MultidrawElement {
            commands: commands.as_slice_any(),
            indices: index_buffer.as_slice_any(),
            data_type: index_buffer.get_indices_type(),
            primitives: index_buffer.get_primitives_type(),
        };

        let (w, h) = display.get_framebuffer_dimensions();
        let persp = cgmath::perspective(cgmath::deg(45.0), w as f32 / h as f32, 0.1, 10000.0);
        let dir = cgmath::Vector3::new(0.0, 0.0, 1.0).normalize();
        let at = cgmath::Vector3::new(0.0, 0.0, 0.0);
        let eye = at - dir.mul_s(250.0);
        let view = cgmath::Matrix4::look_at(&cgmath::Point3::from_vec(&eye),
                                            &cgmath::Point3::from_vec(&at),
                                            &cgmath::Vector3::new(0.0, 0.0, 1.0));
        let pos = cgmath::Matrix4::from_translation(&eye.mul_s(-1.0));
        let matrix = persp * view * pos;

        let params = glium::DrawParameters {
            backface_culling: glium::draw_parameters::BackfaceCullingMode::CullCounterClockWise,
            depth_test: glium::draw_parameters::DepthTest::IfLess,
            depth_write: true,
            .. Default::default()
        };

        let mut target = display.draw();
        target.clear_color_and_depth((0.0, 0.0, 0.01, 1.0), 1.0);
        target.draw(&vertex_buffer, indices, &program,
                    &uniform! { CB0: &transform_buffer, CB1: &cb1, ViewProjection: matrix },
                    &params).unwrap();
        target.finish().unwrap();

        buf_num += 1;
        if buf_num >= 3 { buf_num = 0; }

        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return,
                _ => ()
            }
        }
    }
}
<commit_msg>Fix backface culling<commit_after>#[macro_use]
extern crate glium;
extern crate cgmath;
extern crate rand;

use glium::{DisplayBuild, Surface};
use glium::glutin;
use cgmath::{EuclideanVector, Vector, Point};

#[derive(Copy, Clone)]
struct Vertex {
    position: (f32, f32, f32),
    tex_coords: (f32, f32),
}
implement_vertex!(Vertex, position, tex_coords);

#[derive(Copy, Clone)]
struct DrawId {
    draw_id: u32,
}
implement_vertex!(DrawId, draw_id);

struct Transform {
    transforms: [[[f32; 4]; 4]],
}
implement_buffer_content!(Transform);
implement_uniform_block!(Transform, transforms);

struct Textures<'a> {
    tex_address: [glium::texture::TextureHandle<'a>],
}
implement_buffer_content!(Textures<'a>);
implement_uniform_block!(Textures<'a>, tex_address);

const OBJECTS_X: usize = 100;
const OBJECTS_Y: usize = 100;
const OBJECTS_COUNT: usize = OBJECTS_X * OBJECTS_Y;

fn main() {
    let display = glutin::WindowBuilder::new()
                    .with_depth_buffer(24)
                    .build_glium()
                    .unwrap();

    let vertex_buffer = glium::VertexBuffer::new(&display, &[
        Vertex { position: (-0.5, -0.5, 0.0), tex_coords: (0.0,  0.0) },
        Vertex { position: ( 0.5, -0.5, 0.0), tex_coords: (0.0,  1.0) },
        Vertex { position: ( 0.5,  0.5, 0.0), tex_coords: (1.0,  0.0) },
        Vertex { position: (-0.5,  0.5, 0.0), tex_coords: (1.0,  1.0) },
    ]);

    let index_buffer = glium::index::IndexBuffer::new(&display,
        glium::index::PrimitiveType::TrianglesList,
        &[0, 1, 2, 0, 2, 3u16][..]
    );

    let program = program!(&display,
        410 => {
            vertex: include_str!("../textures_gl_bindless_multidraw_vs.glsl"),
            fragment: include_str!("../textures_gl_bindless_multidraw_fs.glsl"),
        }
    ).unwrap();

    let mut commands = glium::index::DrawCommandsIndicesBuffer::
                                  empty_dynamic_if_supported(&display, OBJECTS_COUNT * 3).unwrap();
    let mut transform_buffer = glium::uniforms::UniformBuffer::<Transform>::empty_unsized_if_supported(&display,
                                                                  16 * 4 * OBJECTS_COUNT).unwrap();

    let textures_storage = (0 .. OBJECTS_COUNT).map(|_| {
        let color1: (f32, f32, f32) = (rand::random(), rand::random(), rand::random());
        let color2: (f32, f32, f32) = (rand::random(), rand::random(), rand::random());
        let texture = glium::texture::Texture2d::new(&display, vec![vec![color1], vec![color2]]);
        texture.resident_if_supported().unwrap()
    }).collect::<Vec<_>>();

    let mut cb1 = glium::uniforms::UniformBuffer::<Textures>::empty_unsized_if_supported(&display, OBJECTS_COUNT * 8).unwrap();
    for (i, element) in cb1.map().tex_address.iter_mut().enumerate() {
        *element = glium::texture::TextureHandle::new(&textures_storage[i], &Default::default());
    }

    let mut iteration = 0;
    let mut buf_num = 0;

    loop {
        // writing the commands
        {
            let commands = commands.slice_mut(buf_num * OBJECTS_COUNT .. (buf_num + 1) * OBJECTS_COUNT).unwrap();
            let len = commands.len();
            let mut commands = commands.map_write();
            for i in 0 .. len {
                commands.set(i, glium::index::DrawCommandIndices {
                    count: index_buffer.len() as u32,
                    instance_count: 1,
                    first_index: 0,
                    base_vertex: 0,
                    base_instance: 0,
                });
            }
        }

        // writing the transforms
        {
            let angle = iteration as f32 * 0.01;
            iteration += 1;
            if angle > 2.0 * 3.141592 {
                iteration = 0;
            }

            let mut transforms = transform_buffer.map();
            let mut index = 0;

            for x in (0 .. OBJECTS_X) {
                for y in (0 .. OBJECTS_Y) {
                    let s = angle.sin();
                    let c = angle.cos();

                    let mut mat = [
                        [c,  -s,   0.0, 0.0],
                        [s,   c,   0.0, 0.0],
                        [0.0, 0.0, 1.0, 0.0],
                        [0.0, 0.0, 0.0, 1.0],
                    ];

                    mat[0][0] = 2.0 * (x as isize - OBJECTS_X as isize) as f32;
                    mat[3][1] = 2.0 * (y as isize - OBJECTS_Y as isize) as f32;
                    mat[3][2] = 0.0;

                    transforms.transforms[index] = mat;
                    index += 1;
                }
            }
        }

        let commands = commands.slice_mut(buf_num * OBJECTS_COUNT .. (buf_num + 1) * OBJECTS_COUNT).unwrap();
        let indices = glium::index::IndicesSource::MultidrawElement {
            commands: commands.as_slice_any(),
            indices: index_buffer.as_slice_any(),
            data_type: index_buffer.get_indices_type(),
            primitives: index_buffer.get_primitives_type(),
        };

        let (w, h) = display.get_framebuffer_dimensions();
        let persp = cgmath::perspective(cgmath::deg(45.0), w as f32 / h as f32, 0.1, 10000.0);
        let dir = cgmath::Vector3::new(0.0, 0.0, 1.0).normalize();
        let at = cgmath::Vector3::new(0.0, 0.0, 0.0);
        let eye = at - dir.mul_s(250.0);
        let view = cgmath::Matrix4::look_at(&cgmath::Point3::from_vec(&eye),
                                            &cgmath::Point3::from_vec(&at),
                                            &cgmath::Vector3::new(0.0, 0.0, 1.0));
        let pos = cgmath::Matrix4::from_translation(&eye.mul_s(-1.0));
        let matrix = persp * view * pos;

        let params = glium::DrawParameters {
            backface_culling: glium::draw_parameters::BackfaceCullingMode::CullClockWise,
            depth_test: glium::draw_parameters::DepthTest::IfLess,
            depth_write: true,
            .. Default::default()
        };

        let mut target = display.draw();
        target.clear_color_and_depth((0.0, 0.0, 0.01, 1.0), 1.0);
        target.draw(&vertex_buffer, indices, &program,
                    &uniform! { CB0: &transform_buffer, CB1: &cb1, ViewProjection: matrix },
                    &params).unwrap();
        target.finish().unwrap();

        buf_num += 1;
        if buf_num >= 3 { buf_num = 0; }

        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return,
                _ => ()
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

#![allow(dead_code)]

use server::Node;
use server::transport::{ServerRaftStoreRouter, RaftStoreRouter};
use raftstore::store::{Transport, Peekable};
use raftstore::errors::Error as RaftServerError;
use raftstore::coprocessor::RegionSnapshot;
use util::HandyRwLock;
use kvproto::raft_cmdpb::{RaftCmdRequest, RaftCmdResponse, RaftRequestHeader, Request, Response,
                          GetRequest, CmdType, SeekRequest, DeleteRequest, PutRequest};
use kvproto::errorpb;
use kvproto::kvrpcpb::Context;

use pd::PdClient;
use uuid::Uuid;
use std::sync::{Arc, RwLock};
use std::sync::mpsc;
use std::fmt::{self, Formatter, Debug};
use std::io::Error as IoError;
use std::result;
use rocksdb::DB;
use protobuf::RepeatedField;

use storage::engine;
use super::{Engine, Modify, Snapshot};
use storage::{Key, Value, KvPair};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        RequestFailed(e: errorpb::Error) {
            from()
            description(e.get_message())
        }
        Io(e: IoError) {
            from()
            cause(e)
            description(e.description())
        }
        RocksDb(reason: String) {
            description(reason)
        }
        Server(e: RaftServerError) {
            from()
            cause(e)
            description(e.description())
        }
        InvalidResponse(reason: String) {
            description(reason)
        }
        InvalidRequest(reason: String) {
            description(reason)
        }
    }
}

pub type Result<T> = result::Result<T, Error>;

impl From<Error> for engine::Error {
    fn from(e: Error) -> engine::Error {
        match e {
            Error::RequestFailed(e) => engine::Error::Request(e),
            e => box_err!(e),
        }
    }
}

/// RaftKv is a storage engine base on RaftKvServer.
pub struct RaftKv<T: PdClient + 'static, Trans: Transport + 'static> {
    node: Node<T, Trans>,
    db: Arc<DB>,
    router: Arc<RwLock<ServerRaftStoreRouter>>,
}

impl<T: PdClient, Trans: Transport> RaftKv<T, Trans> {
    /// Create a RaftKv using specified configuration.
    pub fn new(node: Node<T, Trans>, db: Arc<DB>) -> RaftKv<T, Trans> {
        let router = node.raft_store_router();
        RaftKv {
            node: node,
            db: db,
            router: router,
        }
    }

    fn exec_cmd_request(&self, req: RaftCmdRequest) -> Result<RaftCmdResponse> {
        let (tx, rx) = mpsc::channel();
        let uuid = req.get_header().get_uuid().to_vec();
        let l = req.get_requests().len();

        try!(self.router.rl().send_command(req,
                                           box move |r| {
                                               box_try!(tx.send(r));
                                               Ok(())
                                           }));

        // Only when tx is closed will recv return Err, which should never happen.
        let mut resp = rx.recv().unwrap();
        if resp.get_header().get_uuid() != &*uuid {
            return Err(Error::InvalidResponse("response is not correct!!!".to_owned()));
        }
        if resp.get_header().has_error() {
            return Err(Error::RequestFailed(resp.mut_header().take_error()));
        }
        if l != resp.get_responses().len() {
            return Err(Error::InvalidResponse("response count is not equal to requests, \
                                               something must go wrong."
                                                  .to_owned()));
        }
        Ok(resp)
    }

    fn new_request_header(&self, ctx: &Context) -> RaftRequestHeader {
        let mut header = RaftRequestHeader::new();
        header.set_region_id(ctx.get_region_id());
        header.set_peer(ctx.get_peer().clone());
        header.set_region_epoch(ctx.get_region_epoch().clone());
        header.set_uuid(Uuid::new_v4().as_bytes().to_vec());
        header
    }

    fn exec_requests(&self, ctx: &Context, reqs: Vec<Request>) -> Result<Vec<Response>> {
        let header = self.new_request_header(ctx);
        let mut cmd = RaftCmdRequest::new();
        cmd.set_header(header);
        cmd.set_requests(RepeatedField::from_vec(reqs));
        let mut resp = try!(self.exec_cmd_request(cmd));
        Ok(resp.take_responses().to_vec())
    }

    fn exec_request(&self, ctx: &Context, req: Request) -> Result<Response> {
        let resps = self.exec_requests(ctx, vec![req]);
        resps.map(|mut v| v.remove(0))
    }
}

fn invalid_resp_type(exp: CmdType, act: CmdType) -> engine::Error {
    Error::InvalidResponse(format!("cmd type not match, want {:?}, got {:?}!", exp, act)).into()
}

impl<T: PdClient, Trans: Transport> Debug for RaftKv<T, Trans> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "RaftKv")
    }
}

impl<T: PdClient, Trans: Transport> Engine for RaftKv<T, Trans> {
    fn get(&self, ctx: &Context, key: &Key) -> engine::Result<Option<Value>> {
        let mut get = GetRequest::new();
        get.set_key(key.raw().clone());
        let mut req = Request::new();
        req.set_cmd_type(CmdType::Get);
        req.set_get(get);
        let mut resp = try!(self.exec_request(ctx, req));
        if resp.get_cmd_type() != CmdType::Get {
            return Err(invalid_resp_type(CmdType::Get, resp.get_cmd_type()));
        }
        let get_resp = resp.mut_get();
        if get_resp.has_value() {
            Ok(Some(get_resp.take_value()))
        } else {
            Ok(None)
        }
    }

    fn seek(&self, ctx: &Context, key: &Key) -> engine::Result<Option<KvPair>> {
        let mut seek = SeekRequest::new();
        seek.set_key(key.raw().clone());
        let mut req = Request::new();
        req.set_cmd_type(CmdType::Seek);
        req.set_seek(seek);
        let mut resp = try!(self.exec_request(ctx, req));
        if resp.get_cmd_type() != CmdType::Seek {
            return Err(invalid_resp_type(CmdType::Seek, resp.get_cmd_type()));
        }
        let seek_resp = resp.mut_seek();
        if seek_resp.has_key() {
            Ok(Some((seek_resp.take_key(), seek_resp.take_value())))
        } else {
            Ok(None)
        }
    }

    fn write(&self, ctx: &Context, mut modifies: Vec<Modify>) -> engine::Result<()> {
        if modifies.len() == 0 {
            return Ok(());
        }
        let mut reqs = Vec::with_capacity(modifies.len());
        while !modifies.is_empty() {
            let m = modifies.pop().unwrap();
            let mut req = Request::new();
            match m {
                Modify::Delete(k) => {
                    let mut delete = DeleteRequest::new();
                    delete.set_key(k.raw().clone());
                    req.set_cmd_type(CmdType::Delete);
                    req.set_delete(delete);
                }
                Modify::Put((k, v)) => {
                    let mut put = PutRequest::new();
                    put.set_key(k.raw().clone());
                    put.set_value(v);
                    req.set_cmd_type(CmdType::Put);
                    req.set_put(put);
                }
            }
            reqs.push(req);
        }
        try!(self.exec_requests(ctx, reqs));
        Ok(())
    }

    fn snapshot<'a>(&'a self, ctx: &Context) -> engine::Result<Box<Snapshot + 'a>> {
        let mut req = Request::new();
        req.set_cmd_type(CmdType::Snap);
        let mut resp = try!(self.exec_request(ctx, req));
        if resp.get_cmd_type() != CmdType::Snap {
            return Err(invalid_resp_type(CmdType::Snap, resp.get_cmd_type()));
        }
        let region = resp.take_snap().take_region();
        // TODO figure out a way to create snapshot when apply
        let snap = RegionSnapshot::from_raw(self.db.as_ref(), region);
        Ok(box snap)
    }
}

impl<'a> Snapshot for RegionSnapshot<'a> {
    fn get(&self, key: &Key) -> engine::Result<Option<Value>> {
        let v = box_try!(self.get_value(key.raw()));
        Ok(v.map(|v| v.to_vec()))
    }

    fn seek(&self, key: &Key) -> engine::Result<Option<KvPair>> {
        let pair = box_try!(self.seek(key.raw()));
        Ok(pair)
    }
}
<commit_msg>transport: add timeout (#396)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

#![allow(dead_code)]

use server::Node;
use server::transport::{ServerRaftStoreRouter, RaftStoreRouter};
use raftstore::store::{Transport, Peekable};
use raftstore::errors::Error as RaftServerError;
use raftstore::coprocessor::RegionSnapshot;
use util::HandyRwLock;
use kvproto::raft_cmdpb::{RaftCmdRequest, RaftCmdResponse, RaftRequestHeader, Request, Response,
                          GetRequest, CmdType, SeekRequest, DeleteRequest, PutRequest};
use kvproto::errorpb;
use kvproto::kvrpcpb::Context;

use pd::PdClient;
use uuid::Uuid;
use std::sync::{Arc, RwLock, Mutex, Condvar};
use std::fmt::{self, Formatter, Debug};
use std::io::Error as IoError;
use std::time::Duration;
use std::result;
use rocksdb::DB;
use protobuf::RepeatedField;

use storage::engine;
use super::{Engine, Modify, Snapshot};
use storage::{Key, Value, KvPair};

const DEFAULT_TIMEOUT_SECS: u64 = 5;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        RequestFailed(e: errorpb::Error) {
            from()
            description(e.get_message())
        }
        Io(e: IoError) {
            from()
            cause(e)
            description(e.description())
        }
        RocksDb(reason: String) {
            description(reason)
        }
        Server(e: RaftServerError) {
            from()
            cause(e)
            description(e.description())
        }
        InvalidResponse(reason: String) {
            description(reason)
        }
        InvalidRequest(reason: String) {
            description(reason)
        }
        Timeout(d: Duration) {
            description("request timeout")
            display("timeout after {:?}", d)
        }
    }
}

pub type Result<T> = result::Result<T, Error>;

impl From<Error> for engine::Error {
    fn from(e: Error) -> engine::Error {
        match e {
            Error::RequestFailed(e) => engine::Error::Request(e),
            e => box_err!(e),
        }
    }
}

/// RaftKv is a storage engine base on RaftKvServer.
pub struct RaftKv<T: PdClient + 'static, Trans: Transport + 'static> {
    node: Node<T, Trans>,
    db: Arc<DB>,
    router: Arc<RwLock<ServerRaftStoreRouter>>,
}

impl<T: PdClient, Trans: Transport> RaftKv<T, Trans> {
    /// Create a RaftKv using specified configuration.
    pub fn new(node: Node<T, Trans>, db: Arc<DB>) -> RaftKv<T, Trans> {
        let router = node.raft_store_router();
        RaftKv {
            node: node,
            db: db,
            router: router,
        }
    }

    // TODO: reuse msg code.
    pub fn call_command(&self, request: RaftCmdRequest) -> Result<RaftCmdResponse> {
        let resp: Option<RaftCmdResponse> = None;
        let pair = Arc::new((Mutex::new(resp), Condvar::new()));
        let pair2 = pair.clone();
        let timeout = Duration::from_secs(DEFAULT_TIMEOUT_SECS);

        try!(self.router.rl().send_command(request,
                                           box move |resp| {
                                               let &(ref lock, ref cvar) = &*pair2;
                                               let mut v = lock.lock().unwrap();
                                               *v = Some(resp);
                                               cvar.notify_one();
                                               Ok(())
                                           }));

        let &(ref lock, ref cvar) = &*pair;
        let mut v = lock.lock().unwrap();
        while v.is_none() {
            let (resp, timeout_res) = cvar.wait_timeout(v, timeout).unwrap();
            if timeout_res.timed_out() {
                return Err(Error::Timeout(timeout));
            }

            v = resp
        }

        Ok(v.take().unwrap())
    }

    fn exec_cmd_request(&self, req: RaftCmdRequest) -> Result<RaftCmdResponse> {
        let uuid = req.get_header().get_uuid().to_vec();
        let l = req.get_requests().len();

        // Only when tx is closed will recv return Err, which should never happen.
        let mut resp = try!(self.call_command(req));
        if resp.get_header().get_uuid() != &*uuid {
            return Err(Error::InvalidResponse("response is not correct!!!".to_owned()));
        }
        if resp.get_header().has_error() {
            return Err(Error::RequestFailed(resp.mut_header().take_error()));
        }
        if l != resp.get_responses().len() {
            return Err(Error::InvalidResponse("response count is not equal to requests, \
                                               something must go wrong."
                                                  .to_owned()));
        }
        Ok(resp)
    }

    fn new_request_header(&self, ctx: &Context) -> RaftRequestHeader {
        let mut header = RaftRequestHeader::new();
        header.set_region_id(ctx.get_region_id());
        header.set_peer(ctx.get_peer().clone());
        header.set_region_epoch(ctx.get_region_epoch().clone());
        header.set_uuid(Uuid::new_v4().as_bytes().to_vec());
        header
    }

    fn exec_requests(&self, ctx: &Context, reqs: Vec<Request>) -> Result<Vec<Response>> {
        let header = self.new_request_header(ctx);
        let mut cmd = RaftCmdRequest::new();
        cmd.set_header(header);
        cmd.set_requests(RepeatedField::from_vec(reqs));
        let mut resp = try!(self.exec_cmd_request(cmd));
        Ok(resp.take_responses().to_vec())
    }

    fn exec_request(&self, ctx: &Context, req: Request) -> Result<Response> {
        let resps = self.exec_requests(ctx, vec![req]);
        resps.map(|mut v| v.remove(0))
    }
}

fn invalid_resp_type(exp: CmdType, act: CmdType) -> engine::Error {
    Error::InvalidResponse(format!("cmd type not match, want {:?}, got {:?}!", exp, act)).into()
}

impl<T: PdClient, Trans: Transport> Debug for RaftKv<T, Trans> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "RaftKv")
    }
}

impl<T: PdClient, Trans: Transport> Engine for RaftKv<T, Trans> {
    fn get(&self, ctx: &Context, key: &Key) -> engine::Result<Option<Value>> {
        let mut get = GetRequest::new();
        get.set_key(key.raw().clone());
        let mut req = Request::new();
        req.set_cmd_type(CmdType::Get);
        req.set_get(get);
        let mut resp = try!(self.exec_request(ctx, req));
        if resp.get_cmd_type() != CmdType::Get {
            return Err(invalid_resp_type(CmdType::Get, resp.get_cmd_type()));
        }
        let get_resp = resp.mut_get();
        if get_resp.has_value() {
            Ok(Some(get_resp.take_value()))
        } else {
            Ok(None)
        }
    }

    fn seek(&self, ctx: &Context, key: &Key) -> engine::Result<Option<KvPair>> {
        let mut seek = SeekRequest::new();
        seek.set_key(key.raw().clone());
        let mut req = Request::new();
        req.set_cmd_type(CmdType::Seek);
        req.set_seek(seek);
        let mut resp = try!(self.exec_request(ctx, req));
        if resp.get_cmd_type() != CmdType::Seek {
            return Err(invalid_resp_type(CmdType::Seek, resp.get_cmd_type()));
        }
        let seek_resp = resp.mut_seek();
        if seek_resp.has_key() {
            Ok(Some((seek_resp.take_key(), seek_resp.take_value())))
        } else {
            Ok(None)
        }
    }

    fn write(&self, ctx: &Context, mut modifies: Vec<Modify>) -> engine::Result<()> {
        if modifies.len() == 0 {
            return Ok(());
        }
        let mut reqs = Vec::with_capacity(modifies.len());
        while !modifies.is_empty() {
            let m = modifies.pop().unwrap();
            let mut req = Request::new();
            match m {
                Modify::Delete(k) => {
                    let mut delete = DeleteRequest::new();
                    delete.set_key(k.raw().clone());
                    req.set_cmd_type(CmdType::Delete);
                    req.set_delete(delete);
                }
                Modify::Put((k, v)) => {
                    let mut put = PutRequest::new();
                    put.set_key(k.raw().clone());
                    put.set_value(v);
                    req.set_cmd_type(CmdType::Put);
                    req.set_put(put);
                }
            }
            reqs.push(req);
        }
        try!(self.exec_requests(ctx, reqs));
        Ok(())
    }

    fn snapshot<'a>(&'a self, ctx: &Context) -> engine::Result<Box<Snapshot + 'a>> {
        let mut req = Request::new();
        req.set_cmd_type(CmdType::Snap);
        let mut resp = try!(self.exec_request(ctx, req));
        if resp.get_cmd_type() != CmdType::Snap {
            return Err(invalid_resp_type(CmdType::Snap, resp.get_cmd_type()));
        }
        let region = resp.take_snap().take_region();
        // TODO figure out a way to create snapshot when apply
        let snap = RegionSnapshot::from_raw(self.db.as_ref(), region);
        Ok(box snap)
    }
}

impl<'a> Snapshot for RegionSnapshot<'a> {
    fn get(&self, key: &Key) -> engine::Result<Option<Value>> {
        let v = box_try!(self.get_value(key.raw()));
        Ok(v.map(|v| v.to_vec()))
    }

    fn seek(&self, key: &Key) -> engine::Result<Option<KvPair>> {
        let pair = box_try!(self.seek(key.raw()));
        Ok(pair)
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::io::{BufReader, BufWriter};

use serde_json;

use radio::song::Song;
use util::logger::log;

#[derive(Debug, Serialize, Deserialize)]
pub struct SongMap(HashMap<Song, u8>);

impl SongMap {
    fn new() -> Self {
        SongMap(HashMap::new())
    }

    fn insert(&mut self, key: Song, value: u8) {
        self.0.insert(key, value);
    }

    pub fn insert_song(&mut self, song: Song) {
        let counter = self.0.entry(song).or_insert(0);
        *counter += 1;
    }

    pub fn save_to_file(&self, dir: &str, name: &str) {
        fn save_error(dir: &str, name: &str) {
            log(&format!("ERROR: Could not save {}\\{}.json",dir, name));
        }
        let _ = fs::create_dir_all(dir);
        let to = match File::create(format!("{}\\{}.json",dir, name)) {
            Ok(file) => file,
            Err(_) => {
                save_error(dir, name);
                return
            }
        };
        let mut to = BufWriter::new(to);
        let mut string_vec: Vec<SongMapHelper> = Vec::new();
        for (key, value) in self.0.iter() {
            string_vec.push(
                SongMapHelper {
                    artist: key.artist.clone(),
                    title: key.title.clone(),
                    count: *value,
                }
            );
        }
        match serde_json::to_writer_pretty(&mut to, &string_vec) {
            Err(_) => {
                save_error(dir, name);
                return
            }
            _ => {},
        }
        let _ = to.write(b"\n");
        let _ = to.flush();
    }

    pub fn load_from_file(dir: &str, name: &'static str) -> Self {
        fn load_error(dir: &str, name: &'static str) {
            log(&format!("ERROR: Could not load {}\\{}.json",dir, name));
        }

        let mut song_map = SongMap::new();
        let from = match File::open(format!("{}\\{}.json",dir, name)) {
            Ok(file) => file,
            Err(_) => {
                load_error(dir, name);
                return song_map
            }
        };
        let from = BufReader::new(from);
        let string_vec: Vec<SongMapHelper> = match serde_json::from_reader(from) {
            Ok(vec) => vec,
            Err(_) => {
                load_error(dir, name);
                return song_map
            }
        };
        for song_helper in string_vec {
            song_map.insert( Song {
                artist: song_helper.artist,
                title: song_helper.title
            }, song_helper.count);
        }
        song_map
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct SongMapHelper {
    artist: String,
    title: String,
    count: u8
}
<commit_msg>Deactivate logging in load and save songmap<commit_after>use std::collections::HashMap;
use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::io::{BufReader, BufWriter};

use serde_json;

use radio::song::Song;
//use util::logger::log;

#[derive(Debug, Serialize, Deserialize)]
pub struct SongMap(HashMap<Song, u8>);

impl SongMap {
    fn new() -> Self {
        SongMap(HashMap::new())
    }

    fn insert(&mut self, key: Song, value: u8) {
        self.0.insert(key, value);
    }

    pub fn insert_song(&mut self, song: Song) {
        let counter = self.0.entry(song).or_insert(0);
        *counter += 1;
    }

    pub fn save_to_file(&self, dir: &str, name: &str) {
        //fn save_error(dir: &str, name: &str) {
        //    log(&format!("ERROR: Could not save {}\\{}.json",dir, name));
        //}
        let _ = fs::create_dir_all(dir);
        let to = match File::create(format!("{}\\{}.json",dir, name)) {
            Ok(file) => file,
            Err(_) => {
                //save_error(dir, name);
                return
            }
        };
        let mut to = BufWriter::new(to);
        let mut string_vec: Vec<SongMapHelper> = Vec::new();
        for (key, value) in self.0.iter() {
            string_vec.push(
                SongMapHelper {
                    artist: key.artist.clone(),
                    title: key.title.clone(),
                    count: *value,
                }
            );
        }
        match serde_json::to_writer_pretty(&mut to, &string_vec) {
            Err(_) => {
                //save_error(dir, name);
                return
            }
            _ => {},
        }
        let _ = to.write(b"\n");
        let _ = to.flush();
    }

    pub fn load_from_file(dir: &str, name: &'static str) -> Self {
        //fn load_error(dir: &str, name: &'static str) {
        //    log(&format!("ERROR: Could not load {}\\{}.json",dir, name));
        //}

        let mut song_map = SongMap::new();
        let from = match File::open(format!("{}\\{}.json",dir, name)) {
            Ok(file) => file,
            Err(_) => {
                //load_error(dir, name);
                return song_map
            }
        };
        let from = BufReader::new(from);
        let string_vec: Vec<SongMapHelper> = match serde_json::from_reader(from) {
            Ok(vec) => vec,
            Err(_) => {
                //load_error(dir, name);
                return song_map
            }
        };
        for song_helper in string_vec {
            song_map.insert( Song {
                artist: song_helper.artist,
                title: song_helper.title
            }, song_helper.count);
        }
        song_map
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct SongMapHelper {
    artist: String,
    title: String,
    count: u8
}
<|endoftext|>