<commit_before>use ast::Ast;
use commands::{Command, Type};

use std::io;

pub struct Interpreter {
    values: Vec<Vec<Type>>,
    pointer: usize,
    index: usize,
    value: Type,
    int: Type,
    pc: usize,
    last: usize,
    dojump: bool,
    rep: bool,

    program: Ast,
}

impl Interpreter {

    pub fn new(program: Ast) -> Interpreter {
        Interpreter {
            pointer: 0,
            index: 0,
            int: Type::I(1),
            pc: 0,
            last: 0,
            values: Vec::new(),
            value: Type::I(0),
            dojump: true,
            rep: false,
            program: program,
        }
    }

    fn get_value(&mut self, int: bool) {
        let mut existed = true;
        match self.values.get(self.pointer) {
            Some(value) => {
                match value.get(self.index) {
                    Some(typ) => {
                        if int {
                            self.int = typ.clone();
                        } else {
                            self.value = typ.clone();
                        }
                    },
                    None => {
                        existed = false;
                    },
                }
            },
            None => {
                existed = false;
            },
        }
        if !existed {
            if int {
                self.int = Type::I(0);
            } else {
                self.value = Type::I(0);
            }
        }
    }

    fn set_value(&mut self, int: bool) {
        if self.values.len() < self.pointer + 1 {
            self.values.resize(self.pointer + 1, Vec::new());
            let mut vec = vec![Type::I(0); self.index + 1];
            if int {
                vec[self.index] = self.int.clone();
            } else {
                vec[self.index] = self.value.clone();
            }
            self.values[self.pointer] = vec;
            return;
        }

        if self.values[self.pointer].len() < self.index + 1 {
            self.values[self.pointer].resize(self.index + 1, Type::I(0));
        }

        if int {
            self.values[self.pointer][self.index] = self.int.clone();
        } else {
            self.values[self.pointer][self.index] = self.value.clone();
        }
    }

    pub fn run(&mut self) -> usize {
        loop {
            let command = self.program[self.pc].clone();

            match command {
                Command::Nil => {
                    break;
                },
                //loopable commands
                //Command::Out |
                //Command::OutL |
                Command::Incr |
                Command::Decr |
                Command::NMar |
                Command::PMar |
                Command::NInd |
                Command::PInd |
                Command::Down |
                Command::Up |
                Command::Rep |
                Command::Next(_) |
                Command::Prev(_) |
                Command::Grp(_) => {

                    //interpret command
                    let mut loops = match self.int {
                        Type::I(int) => int,
                        _ => 1,
                    };
                    while loops > 0 {
                        if loops == 1 {
                            self.int = Type::I(1);
                        }
                        self.interpret(&command);
                        loops = loops - 1;
                    }
                },
                command => {
                    self.interpret(&command);
                },
            }
            self.pc = self.pc + 1;
        }
        0
    }

    fn interpret(&mut self, command: &Command) {
        match command {
            &Command::VOut => {
                if !self.rep {
                    self.last = self.pc;
                }
                print!("{}", self.value);
            },
            &Command::VOutL => {
                if !self.rep {
                    self.last = self.pc;
                }
                println!("{}", self.value);
            },
            &Command::IOut => {
                if !self.rep {
                    self.last = self.pc;
                }
                print!("{}", self.int);
            },
            &Command::IOutL => {
                if !self.rep {
                    self.last = self.pc;
                }
                println!("{}", self.int);
            },
            &Command::In => {
                let mut input = String::new();
                match io::stdin().read_line(&mut input) {
                    Ok(_) => {
                        input = input.trim().to_owned();
                        let val = match input.parse::<i64>() {
                            Ok(n) => Type::I(n),
                            Err(_) => Type::S(input),
                        };
                        self.value = val.clone();
                    },
                    _ => (),
                }
            },
            &Command::Put => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.set_value(false);
            },
            &Command::PutI => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.set_value(true);
            },
            &Command::Yank => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.get_value(false);
            },
            &Command::YankI => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.get_value(true);
            },
            &Command::InsV(ref val) => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.value = val.clone();
                self.set_value(false);
            },
            &Command::InsI(ref val) => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.int = val.clone();
                self.set_value(true);
            },
            &Command::Incr => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.get_value(false);
                match self.value {
                    Type::I(v) => {
                        self.value = Type::I(v + 1);
                        self.set_value(false);
                    }
                    _ => (),
                }
            },
            &Command::Decr => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.get_value(false);
                match self.value {
                    Type::I(v) => {
                        self.value = Type::I(v - 1);
                        self.set_value(false);
                    }
                    _ => (),
                }
            },
            &Command::Plus => {
                let val = self.value.get_int();
                let int = self.int.get_int();
                self.value = Type::I(val + int);
                self.int = Type::I(1);
            },
            &Command::Minus => {
                let val = self.value.get_int();
                let int = self.int.get_int();
                self.value = Type::I(val - int);
                self.int = Type::I(1);
            },
            &Command::Times => {
                let val = self.value.get_int();
                let int = self.int.get_int();
                self.value = Type::I(val * int);
                self.int = Type::I(1);
            },
            &Command::Divide => {
                let val = self.value.get_int();
                let int = self.int.get_int();
                self.value = Type::I(val / int);
                self.int = Type::I(val % int);
            },
            &Command::Mark(ref mark) => {
                match mark {
                    &'a' ... 'z' => {
                        self.pointer = mark.to_digit(36).unwrap() as usize - 10;
                        self.index = 0;
                    },
                    _ => { panic!("mark must be a to z"); },
                }
            },
            &Command::Ind(ref mark) => {
                match mark {
                    &'a' ... 'z' => {
                        self.pointer = mark.to_digit(36).unwrap() as usize - 10;
                        self.index = self.int.get_int() as usize;
                    },
                    _ => { panic!("mark must be a to z"); },
                }
                self.int = Type::I(1);
            },
            &Command::NMar => {
                self.pointer = self.pointer + 1;
                if self.pointer > 26 {
                    self.pointer = 0;
                }
                self.index = 0;
            },
            &Command::PMar => {
                if self.pointer == 0 {
                    self.pointer = 27;
                }
                self.pointer = self.pointer - 1;
                self.index = 0;
            },
            &Command::NInd => {
                self.index = self.index + 1;
            },
            &Command::PInd => {
                if self.index == 0 {
                    panic!("Can't decrement index, already 0");
                }
                self.index = self.index - 1;
            },
            &Command::Down => {
                if self.dojump {
                    let mut new_pc = self.pc + 1;
                    for i in new_pc..self.program.len() {
                        match self.program[i] {
                            Command::Nil => {
                                new_pc = i- 1;
                                break;
                            }
                            Command::Line => {
                                new_pc = i;
                                break;
                            },
                            _ => (),
                        }
                    }
                    self.pc = new_pc;
                }
                if self.int.get_int() == 1 {
                    self.dojump = true;
                }
            },
            &Command::Up => {
                if self.dojump {
                    let mut new_pc = self.pc + 1;
                    let mut ignore_one = 1;
                    for i in (0..new_pc).rev() {
                        match self.program[i] {
                            Command::Line => {
                                new_pc = i;
                                //break;
                                if ignore_one == 0 {
                                    break;
                                }
                                ignore_one = ignore_one - 1;
                            },
                            _ => (),
                        }
                    }
                    self.pc = new_pc;
                }
                if self.int.get_int() == 1 {
                    self.dojump = true;
                }
            },
            &Command::BLine => {
                if self.dojump {
                    let mut new_pc = self.pc + 1;
                    for i in (0..new_pc).rev() {
                        match self.program[i] {
                            Command::Line => {
                                new_pc = i;
                                break;
                            }
                            _ => (),
                        }
                    }
                    self.pc = new_pc;
                }
                self.dojump = true;
            }
            &Command::Next(ref next) => {
                let mut found = false;
                if self.dojump {
                    let mut new_pc = self.pc + 1;
                    for i in new_pc..self.program.len() {
                        if self.program[i].discriminant() == (**next).discriminant() {
                            new_pc = i;
                            found = true;
                            break;
                        }
                    }
                    if found {
                        self.pc = new_pc;
                    }
                }
                if self.int.get_int() == 1 {
                    self.dojump = true;
                    if found {
                        self.pc = self.pc - 1;
                    }
                }
            },
            &Command::Prev(ref prev) => {
                let mut found = false;
                if self.dojump {
                    let mut new_pc = self.pc + 1;
                    for i in (0..new_pc).rev() {
                        if self.program[i].discriminant() == (**prev).discriminant() {
                            new_pc = i - 1;
                            found = true;
                            break;
                        }
                    }
                    if found {
                        self.pc = new_pc;
                    }
                }
                if self.int.get_int() == 1 {
                    self.dojump = true;
                }
            },
            &Command::Con => {
                self.dojump = self.value == self.int;
                self.int = Type::I(1);
            },
            &Command::NCon => {
                self.dojump = self.value != self.int;
                self.int = Type::I(1);
            },
            &Command::LCon => {
                self.dojump = self.value > self.int;
                self.int = Type::I(1);
            },
            &Command::GCon => {
                self.dojump = self.value < self.int;
                self.int = Type::I(1);
            },
            &Command::Int(ref int) => { self.int = Type::I(int.clone() as i64); },
            &Command::V2I => {
                self.int = self.value.clone();
            },
            &Command::I2V => {
                self.value = self.int.clone();
            }
            &Command::Grp(ref group) => {
                self.do_group(group);
            },
            &Command::Rep => {
                self.rep = true;
                if self.last > 0 {
                    let command = self.program[self.last].clone();
                    self.interpret(&command);
                }
                self.rep = false;
            }
            _ => (),
        }
    }

    fn do_group(&mut self, group: &Ast) {
        let temp_last = self.last;
        self.last = 0;
        let temp_int = self.int.clone();
        self.int = Type::I(1);
        let temp_pc = self.pc;
        self.pc = 0;
        let temp_program = self.program.clone();
        self.program = group.clone();
        loop {
            if self.pc > group.len() - 1 {
                break;
            }

            let command = group[self.pc].clone();

            match command {
                Command::Nil => {
                    break;
                },
                //loopable commands
                Command::Incr |
                Command::Decr |
                Command::NMar |
                Command::PMar |
                Command::NInd |
                Command::PInd |
                Command::Down |
                Command::Up |
                Command::Rep |
                Command::Next(_) |
                Command::Prev(_) |
                Command::Grp(_) => {

                    //interpret command
                    let mut loops = match self.int {
                        Type::I(int) => int,
                        _ => 1,
                    };
                    while loops > 0 {
                        if loops == 1 {
                            self.int = Type::I(1);
                        }
                        self.interpret(&command);
                        loops = loops - 1;
                    }
                },
                command => {
                    self.interpret(&command);
                },
            }
            self.pc = self.pc + 1;
        }
        self.last = temp_last;
        self.int = temp_int.clone();
        self.pc = temp_pc;
        self.program = temp_program;
    }
}

pub fn run(program: Ast) -> usize {
    let mut interpreter = Interpreter::new(program);
    interpreter.run();
    //println!("{:?}", interpreter.values);
    0
}
<commit_msg>Replace memory vec of vecs with array of vecs<commit_after>use ast::Ast;
use commands::{Command, Type};

use std::io;

pub struct Interpreter {
    values: [Vec<Type>; 26],
    pointer: usize,
    index: usize,
    value: Type,
    int: Type,
    pc: usize,
    last: usize,
    dojump: bool,
    rep: bool,

    program: Ast,
}

impl Interpreter {

    pub fn new(program: Ast) -> Interpreter {
        Interpreter {
            pointer: 0,
            index: 0,
            int: Type::I(1),
            pc: 0,
            last: 0,
            values: [vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!(),vec!()],
            value: Type::I(0),
            dojump: true,
            rep: false,
            program: program,
        }
    }

    fn get_value(&mut self, int: bool) {
        match self.values[self.pointer].get(self.index) {
            Some(typ) => {
                if int {
                    self.int = typ.clone();
                } else {
                    self.value = typ.clone();
                }
            },
            None => {
                if int {
                    self.int = Type::I(0);
                } else {
                    self.value = Type::I(0);
                }
            },
        }
    }

    fn set_value(&mut self, int: bool) {
        if self.values[self.pointer].len() < self.index + 1 {
            self.values[self.pointer].resize(self.index + 1, Type::I(0));
        }

        if int {
            self.values[self.pointer][self.index] = self.int.clone();
        } else {
            self.values[self.pointer][self.index] = self.value.clone();
        }
    }

    pub fn run(&mut self) -> usize {
        loop {
            let command = self.program[self.pc].clone();

            match command {
                Command::Nil => {
                    break;
                },
                //loopable commands
                Command::Incr |
                Command::Decr |
                Command::NMar |
                Command::PMar |
                Command::NInd |
                Command::PInd |
                Command::Down |
                Command::Up |
                Command::Rep |
                Command::Next(_) |
                Command::Prev(_) |
                Command::Grp(_) => {

                    //interpret command
                    let mut loops = match self.int {
                        Type::I(int) => int,
                        _ => 1,
                    };
                    while loops > 0 {
                        if loops == 1 {
                            self.int = Type::I(1);
                        }
                        self.interpret(&command);
                        loops = loops - 1;
                    }
                },
                command => {
                    self.interpret(&command);
                },
            }
            self.pc = self.pc + 1;
        }
        0
    }

    fn interpret(&mut self, command: &Command) {
        match command {
            &Command::VOut => {
                if !self.rep {
                    self.last = self.pc;
                }
                print!("{}", self.value);
            },
            &Command::VOutL => {
                if !self.rep {
                    self.last = self.pc;
                }
                println!("{}", self.value);
            },
            &Command::IOut => {
                if !self.rep {
                    self.last = self.pc;
                }
                print!("{}", self.int);
            },
            &Command::IOutL => {
                if !self.rep {
                    self.last = self.pc;
                }
                println!("{}", self.int);
            },
            &Command::In => {
                let mut input = String::new();
                match io::stdin().read_line(&mut input) {
                    Ok(_) => {
                        input = input.trim().to_owned();
                        let val = match input.parse::<i64>() {
                            Ok(n) => Type::I(n),
                            Err(_) => Type::S(input),
                        };
                        self.value = val.clone();
                    },
                    _ => (),
                }
            },
            &Command::Put => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.set_value(false);
            },
            &Command::PutI => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.set_value(true);
            },
            &Command::Yank => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.get_value(false);
            },
            &Command::YankI => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.get_value(true);
            },
            &Command::InsV(ref val) => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.value = val.clone();
                self.set_value(false);
            },
            &Command::InsI(ref val) => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.int = val.clone();
                self.set_value(true);
            },
            &Command::Incr => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.get_value(false);
                match self.value {
                    Type::I(v) => {
                        self.value = Type::I(v + 1);
                        self.set_value(false);
                    }
                    _ => (),
                }
            },
            &Command::Decr => {
                if !self.rep {
                    self.last = self.pc;
                }
                self.get_value(false);
                match self.value {
                    Type::I(v) => {
                        self.value = Type::I(v - 1);
                        self.set_value(false);
                    }
                    _ => (),
                }
            },
            &Command::Plus => {
                let val = self.value.get_int();
                let int = self.int.get_int();
                self.value = Type::I(val + int);
                self.int = Type::I(1);
            },
            &Command::Minus => {
                let val = self.value.get_int();
                let int = self.int.get_int();
                self.value = Type::I(val - int);
                self.int = Type::I(1);
            },
            &Command::Times => {
                let val = self.value.get_int();
                let int = self.int.get_int();
                self.value = Type::I(val * int);
                self.int = Type::I(1);
            },
            &Command::Divide => {
                let val = self.value.get_int();
                let int = self.int.get_int();
                self.value = Type::I(val / int);
                self.int = Type::I(val % int);
            },
            &Command::Mark(ref mark) => {
                match mark {
                    &'a' ... 'z' => {
                        self.pointer = mark.to_digit(36).unwrap() as usize - 10;
                        self.index = 0;
                    },
                    _ => { panic!("mark must be a to z"); },
                }
            },
            &Command::Ind(ref mark) => {
                match mark {
                    &'a' ... 'z' => {
                        self.pointer = mark.to_digit(36).unwrap() as usize - 10;
                        self.index = self.int.get_int() as usize;
                    },
                    _ => { panic!("mark must be a to z"); },
                }
                self.int = Type::I(1);
            },
            &Command::NMar => {
                self.pointer = self.pointer + 1;
                if self.pointer > 26 {
                    self.pointer = 0;
                }
                self.index = 0;
            },
            &Command::PMar => {
                if self.pointer == 0 {
                    self.pointer = 27;
                }
                self.pointer = self.pointer - 1;
                self.index = 0;
            },
            &Command::NInd => {
                self.index = self.index + 1;
            },
            &Command::PInd => {
                if self.index == 0 {
                    panic!("Can't decrement index, already 0");
                }
                self.index = self.index - 1;
            },
            &Command::Down => {
                if self.dojump {
                    let mut new_pc = self.pc + 1;
                    for i in new_pc..self.program.len() {
                        match self.program[i] {
                            Command::Nil => {
                                new_pc = i- 1;
                                break;
                            }
                            Command::Line => {
                                new_pc = i;
                                break;
                            },
                            _ => (),
                        }
                    }
                    self.pc = new_pc;
                }
                if self.int.get_int() == 1 {
                    self.dojump = true;
                }
            },
            &Command::Up => {
                if self.dojump {
                    let mut new_pc = self.pc + 1;
                    let mut ignore_one = 1;
                    for i in (0..new_pc).rev() {
                        match self.program[i] {
                            Command::Line => {
                                new_pc = i;
                                //break;
                                if ignore_one == 0 {
                                    break;
                                }
                                ignore_one = ignore_one - 1;
                            },
                            _ => (),
                        }
                    }
                    self.pc = new_pc;
                }
                if self.int.get_int() == 1 {
                    self.dojump = true;
                }
            },
            &Command::BLine => {
                if self.dojump {
                    let mut new_pc = self.pc + 1;
                    for i in (0..new_pc).rev() {
                        match self.program[i] {
                            Command::Line => {
                                new_pc = i;
                                break;
                            }
                            _ => (),
                        }
                    }
                    self.pc = new_pc;
                }
                self.dojump = true;
            }
            &Command::Next(ref next) => {
                let mut found = false;
                if self.dojump {
                    let mut new_pc = self.pc + 1;
                    for i in new_pc..self.program.len() {
                        if self.program[i].discriminant() == (**next).discriminant() {
                            new_pc = i;
                            found = true;
                            break;
                        }
                    }
                    if found {
                        self.pc = new_pc;
                    }
                }
                if self.int.get_int() == 1 {
                    self.dojump = true;
                    if found {
                        self.pc = self.pc - 1;
                    }
                }
            },
            &Command::Prev(ref prev) => {
                let mut found = false;
                if self.dojump {
                    let mut new_pc = self.pc + 1;
                    for i in (0..new_pc).rev() {
                        if self.program[i].discriminant() == (**prev).discriminant() {
                            new_pc = i - 1;
                            found = true;
                            break;
                        }
                    }
                    if found {
                        self.pc = new_pc;
                    }
                }
                if self.int.get_int() == 1 {
                    self.dojump = true;
                }
            },
            &Command::Con => {
                self.dojump = self.value == self.int;
                self.int = Type::I(1);
            },
            &Command::NCon => {
                self.dojump = self.value != self.int;
                self.int = Type::I(1);
            },
            &Command::LCon => {
                self.dojump = self.value > self.int;
                self.int = Type::I(1);
            },
            &Command::GCon => {
                self.dojump = self.value < self.int;
                self.int = Type::I(1);
            },
            &Command::Int(ref int) => { self.int = Type::I(int.clone() as i64); },
            &Command::V2I => {
                self.int = self.value.clone();
            },
            &Command::I2V => {
                self.value = self.int.clone();
            }
            &Command::Grp(ref group) => {
                self.do_group(group);
            },
            &Command::Rep => {
                self.rep = true;
                if self.last > 0 {
                    let command = self.program[self.last].clone();
                    self.interpret(&command);
                }
                self.rep = false;
            }
            _ => (),
        }
    }

    fn do_group(&mut self, group: &Ast) {
        let temp_last = self.last;
        self.last = 0;
        let temp_int = self.int.clone();
        self.int = Type::I(1);
        let temp_pc = self.pc;
        self.pc = 0;
        let temp_program = self.program.clone();
        self.program = group.clone();
        loop {
            if self.pc > group.len() - 1 {
                break;
            }

            let command = group[self.pc].clone();

            match command {
                Command::Nil => {
                    break;
                },
                //loopable commands
                Command::Incr |
                Command::Decr |
                Command::NMar |
                Command::PMar |
                Command::NInd |
                Command::PInd |
                Command::Down |
                Command::Up |
                Command::Rep |
                Command::Next(_) |
                Command::Prev(_) |
                Command::Grp(_) => {

                    //interpret command
                    let mut loops = match self.int {
                        Type::I(int) => int,
                        _ => 1,
                    };
                    while loops > 0 {
                        if loops == 1 {
                            self.int = Type::I(1);
                        }
                        self.interpret(&command);
                        loops = loops - 1;
                    }
                },
                command => {
                    self.interpret(&command);
                },
            }
            self.pc = self.pc + 1;
        }
        self.last = temp_last;
        self.int = temp_int;
        self.pc = temp_pc;
        self.program = temp_program;
    }
}

pub fn run(program: Ast) -> usize {
    let mut interpreter = Interpreter::new(program);
    interpreter.run();
    //println!("{:?}", interpreter.values);
    0
}
<|endoftext|>


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

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

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

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

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

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

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

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

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

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

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

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

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

pub struct StatementInterpreter {
    environment: Environment,
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}
<commit_msg>Test arithmetic expression<commit_after>use ast::*;
use std::collections::HashMap;
use std::io;
use std::io::prelude::*;

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

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

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

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

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

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

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

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

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

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

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

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

pub struct StatementInterpreter {
    environment: Environment,
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}
<|endoftext|>


<commit_before>//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free[^free] foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! [^free]: Strictly speaking, there are some symbols which are needed but
//!          they aren't always necessary.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! # How to use the core library
//!
//! Please note that all of these details are currently not considered stable.
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [compiler-builtins crate](https://crates.io/crates/compiler_builtins).
//!
//! * `rust_begin_panic` - This function takes four arguments, a
//!   `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments
//!   dictate the panic message, the file at which panic was invoked, and the
//!   line and column inside the file. It is up to consumers of this core
//!   library to define this panic function; it is only required to never
//!   return. This requires a `lang` attribute named `panic_impl`.
//!
//! * `rust_eh_personality` - is used by the failure mechanisms of the
//!    compiler. This is often mapped to GCC's personality function, but crates
//!    which do not trigger a panic can be assured that this function is never
//!    called. The `lang` attribute is called `eh_personality`.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.
//
// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
// this, both the generated test artifact and the linked libtest (which
// transitively includes libcore) will both define the same set of lang items,
// and this will cause the E0152 "duplicate lang item found" error. See
// discussion in #50466 for details.
//
// This cfg won't affect doc tests.
#![cfg(not(test))]

#![stable(feature = "core", since = "1.6.0")]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
       test(no_crate_inject, attr(deny(warnings))),
       test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
#![no_core]

#![warn(deprecated_in_future)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
#![allow(explicit_outlives_requirements)]
#![allow(incomplete_features)]

#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(asm)]
#![feature(bound_cloned)]
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(const_fn_union)]
#![feature(const_generics)]
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
#![feature(doc_spotlight)]
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(is_sorted)]
#![feature(iter_once_with)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(never_type)]
#![feature(nll)]
#![feature(exhaustive_patterns)]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(prelude_import)]
#![feature(repr_simd, platform_intrinsics)]
#![feature(rustc_attrs)]
#![feature(rustc_const_unstable)]
#![feature(simd_ffi)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(stmt_expr_attributes)]
#![feature(transparent_unions)]
#![feature(unboxed_closures)]
#![feature(unsized_locals)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(doc_alias)]
#![feature(mmx_target_feature)]
#![feature(tbm_target_feature)]
#![feature(sse4a_target_feature)]
#![feature(arm_target_feature)]
#![feature(powerpc_target_feature)]
#![feature(mips_target_feature)]
#![feature(aarch64_target_feature)]
#![feature(wasm_target_feature)]
#![feature(avx512_target_feature)]
#![feature(cmpxchg16b_target_feature)]
#![feature(rtm_target_feature)]
#![feature(f16c_target_feature)]
#![feature(hexagon_target_feature)]
#![feature(const_int_conversion)]
#![feature(const_transmute)]
#![cfg_attr(bootstrap, feature(non_exhaustive))]
#![feature(structural_match)]
#![feature(abi_unadjusted)]
#![feature(adx_target_feature)]
#![feature(maybe_uninit_slice)]
#![feature(external_doc)]
#![feature(associated_type_bounds)]

#[prelude_import]
#[allow(unused)]
use prelude::v1::*;

#[macro_use]
mod macros;

#[macro_use]
mod internal_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"] pub mod isize;
#[path = "num/i8.rs"]    pub mod i8;
#[path = "num/i16.rs"]   pub mod i16;
#[path = "num/i32.rs"]   pub mod i32;
#[path = "num/i64.rs"]   pub mod i64;
#[path = "num/i128.rs"]  pub mod i128;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]    pub mod u8;
#[path = "num/u16.rs"]   pub mod u16;
#[path = "num/u32.rs"]   pub mod u32;
#[path = "num/u64.rs"]   pub mod u64;
#[path = "num/u128.rs"]  pub mod u128;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod ptr;
pub mod hint;

/* Core language traits */

pub mod marker;
pub mod ops;
pub mod cmp;
pub mod clone;
pub mod default;
pub mod convert;
pub mod borrow;

/* Core types and methods on primitives */

pub mod any;
pub mod array;
pub mod ascii;
pub mod sync;
pub mod cell;
pub mod char;
pub mod panic;
pub mod panicking;
pub mod pin;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;
pub mod ffi;

pub mod slice;
pub mod str;
pub mod hash;
pub mod fmt;
pub mod time;

pub mod unicode;

/* Async */
pub mod future;
pub mod task;

/* Heap memory allocator trait */
#[allow(missing_docs)]
pub mod alloc;

// note: does not need to be public
mod bool;
mod tuple;
mod unit;

// Pull in the `core_arch` crate directly into libcore. The contents of
// `core_arch` are in a different repository: rust-lang/stdarch.
//
// `core_arch` depends on libcore, but the contents of this module are
// set up in such a way that directly pulling it here works such that the
// crate uses the this crate as its libcore.
#[path = "../stdarch/crates/core_arch/src/mod.rs"]
#[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)]
#[unstable(feature = "stdsimd", issue = "48556")]
mod core_arch;

#[stable(feature = "simd_arch", since = "1.27.0")]
pub use core_arch::arch;
<commit_msg>Rollup merge of #65981 - RalfJung:check-your-gates, r=Centril<commit_after>//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free[^free] foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! [^free]: Strictly speaking, there are some symbols which are needed but
//!          they aren't always necessary.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! # How to use the core library
//!
//! Please note that all of these details are currently not considered stable.
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [compiler-builtins crate](https://crates.io/crates/compiler_builtins).
//!
//! * `rust_begin_panic` - This function takes four arguments, a
//!   `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments
//!   dictate the panic message, the file at which panic was invoked, and the
//!   line and column inside the file. It is up to consumers of this core
//!   library to define this panic function; it is only required to never
//!   return. This requires a `lang` attribute named `panic_impl`.
//!
//! * `rust_eh_personality` - is used by the failure mechanisms of the
//!    compiler. This is often mapped to GCC's personality function, but crates
//!    which do not trigger a panic can be assured that this function is never
//!    called. The `lang` attribute is called `eh_personality`.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.
//
// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
// this, both the generated test artifact and the linked libtest (which
// transitively includes libcore) will both define the same set of lang items,
// and this will cause the E0152 "duplicate lang item found" error. See
// discussion in #50466 for details.
//
// This cfg won't affect doc tests.
#![cfg(not(test))]

#![stable(feature = "core", since = "1.6.0")]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
       test(no_crate_inject, attr(deny(warnings))),
       test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
#![no_core]

#![warn(deprecated_in_future)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
#![allow(explicit_outlives_requirements)]
#![allow(incomplete_features)]

#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(asm)]
#![feature(bound_cloned)]
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(const_fn_union)]
#![feature(const_generics)]
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
#![feature(doc_spotlight)]
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(is_sorted)]
#![feature(iter_once_with)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(never_type)]
#![feature(nll)]
#![feature(exhaustive_patterns)]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(prelude_import)]
#![feature(repr_simd, platform_intrinsics)]
#![feature(rustc_attrs)]
#![feature(rustc_const_unstable)]
#![feature(simd_ffi)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(stmt_expr_attributes)]
#![feature(transparent_unions)]
#![feature(unboxed_closures)]
#![feature(unsized_locals)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(doc_alias)]
#![feature(mmx_target_feature)]
#![feature(tbm_target_feature)]
#![feature(sse4a_target_feature)]
#![feature(arm_target_feature)]
#![feature(powerpc_target_feature)]
#![feature(mips_target_feature)]
#![feature(aarch64_target_feature)]
#![feature(wasm_target_feature)]
#![feature(avx512_target_feature)]
#![feature(cmpxchg16b_target_feature)]
#![feature(rtm_target_feature)]
#![feature(f16c_target_feature)]
#![feature(hexagon_target_feature)]
#![feature(const_int_conversion)]
#![feature(const_transmute)]
#![cfg_attr(bootstrap, feature(non_exhaustive))]
#![feature(structural_match)]
#![feature(abi_unadjusted)]
#![feature(adx_target_feature)]
#![feature(maybe_uninit_slice)]
#![feature(external_doc)]
#![feature(associated_type_bounds)]

#[prelude_import]
#[allow(unused)]
use prelude::v1::*;

#[cfg(not(test))] // See #65860
#[macro_use]
mod macros;

#[macro_use]
mod internal_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"] pub mod isize;
#[path = "num/i8.rs"]    pub mod i8;
#[path = "num/i16.rs"]   pub mod i16;
#[path = "num/i32.rs"]   pub mod i32;
#[path = "num/i64.rs"]   pub mod i64;
#[path = "num/i128.rs"]  pub mod i128;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]    pub mod u8;
#[path = "num/u16.rs"]   pub mod u16;
#[path = "num/u32.rs"]   pub mod u32;
#[path = "num/u64.rs"]   pub mod u64;
#[path = "num/u128.rs"]  pub mod u128;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod ptr;
pub mod hint;

/* Core language traits */

#[cfg(not(test))] // See #65860
pub mod marker;
pub mod ops;
#[cfg(not(test))] // See #65860
pub mod cmp;
#[cfg(not(test))] // See #65860
pub mod clone;
#[cfg(not(test))] // See #65860
pub mod default;
pub mod convert;
pub mod borrow;

/* Core types and methods on primitives */

pub mod any;
#[cfg(not(test))] // See #65860
pub mod array;
pub mod ascii;
pub mod sync;
pub mod cell;
pub mod char;
pub mod panic;
pub mod panicking;
#[cfg(not(test))] // See #65860
pub mod pin;
#[cfg(not(test))] // See #65860
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;
pub mod ffi;

pub mod slice;
#[cfg(not(test))] // See #65860
pub mod str;
#[cfg(not(test))] // See #65860
pub mod hash;
#[cfg(not(test))] // See #65860
pub mod fmt;
pub mod time;

pub mod unicode;

/* Async */
#[cfg(not(test))] // See #65860
pub mod future;
pub mod task;

/* Heap memory allocator trait */
#[allow(missing_docs)]
pub mod alloc;

// note: does not need to be public
mod bool;
mod tuple;
mod unit;

// Pull in the `core_arch` crate directly into libcore. The contents of
// `core_arch` are in a different repository: rust-lang/stdarch.
//
// `core_arch` depends on libcore, but the contents of this module are
// set up in such a way that directly pulling it here works such that the
// crate uses the this crate as its libcore.
#[path = "../stdarch/crates/core_arch/src/mod.rs"]
#[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)]
#[unstable(feature = "stdsimd", issue = "48556")]
mod core_arch;

#[stable(feature = "simd_arch", since = "1.27.0")]
pub use core_arch::arch;
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use backend::Backend;
use connection::Connection;
use deserialize::QueryableByName;
use query_builder::{AstPass, QueryFragment, QueryId};
use query_dsl::{LoadQuery, RunQueryDsl};
use result::QueryResult;
use serialize::ToSql;
use sql_types::HasSqlType;

#[derive(Debug, Clone)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
/// The return value of `sql_query`.
///
/// Unlike most queries in Diesel, `SqlQuery` loads its data by column name,
/// rather than by index. This means that you cannot deserialize this query into
/// a tuple, and any structs used must implement `QueryableByName`.
///
/// See [`sql_query`](../fn.sql_query.html) for examples.
pub struct SqlQuery<Inner = ()> {
    inner: Inner,
    query: String,
}

impl<Inner> SqlQuery<Inner> {
    pub(crate) fn new(inner: Inner, query: String) -> Self {
        SqlQuery { inner, query }
    }

    /// Bind a value for use with this SQL query.
    ///
    /// # Safety
    ///
    /// This function should be used with care, as Diesel cannot validate that
    /// the value is of the right type nor can it validate that you have passed
    /// the correct number of parameters.
    ///
    /// # Example
    ///
    /// ```
    /// # #[macro_use] extern crate diesel;
    /// # include!("../doctest_setup.rs");
    /// #
    /// # use schema::users;
    /// #
    /// # #[derive(QueryableByName, Debug, PartialEq)]
    /// # #[table_name="users"]
    /// # struct User {
    /// #     id: i32,
    /// #     name: String,
    /// # }
    /// #
    /// # fn main() {
    /// #     use diesel::sql_query;
    /// #     use diesel::sql_types::{Integer, Text};
    /// #
    /// #     let connection = establish_connection();
    /// #     diesel::insert_into(users::table)
    /// #         .values(users::name.eq("Jim"))
    /// #         .execute(&connection).unwrap();
    /// # #[cfg(feature = "postgres")]
    /// # let users = sql_query("SELECT * FROM users WHERE id > $1 AND name != $2");
    /// # #[cfg(not(feature = "postgres"))]
    /// let users = sql_query("SELECT * FROM users WHERE id > ? AND name <> ?")
    /// # ;
    /// # let users = users
    ///     .bind::<Integer, _>(1)
    ///     .bind::<Text, _>("Tess")
    ///     .get_results(&connection);
    /// let expected_users = vec![
    ///     User { id: 3, name: "Jim".into() },
    /// ];
    /// assert_eq!(Ok(expected_users), users);
    /// # }
    /// ```
    pub fn bind<ST, Value>(self, value: Value) -> UncheckedBind<Self, Value, ST> {
        UncheckedBind::new(self, value)
    }

    /// Internally boxes future calls on `bind` and `sql` so that they don't
    /// change the type.
    ///
    /// This allows doing things you otherwise couldn't do, e.g. `bind`ing in a
    /// loop.
    pub fn into_boxed<'f, DB: Backend>(self) -> BoxedSqlQuery<'f, DB, Self> {
        BoxedSqlQuery::new(self)
    }

    /// Appends a piece of SQL code at the end.
    pub fn sql<T: AsRef<str>>(mut self, sql: T) -> Self {
        self.query += sql.as_ref();
        self
    }
}

impl<DB, Inner> QueryFragment<DB> for SqlQuery<Inner>
where
    DB: Backend,
    Inner: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();
        self.inner.walk_ast(out.reborrow())?;
        out.push_sql(&self.query);
        Ok(())
    }
}

impl<Inner> QueryId for SqlQuery<Inner> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<Inner, Conn, T> LoadQuery<Conn, T> for SqlQuery<Inner>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend>,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Inner, Conn> RunQueryDsl<Conn> for SqlQuery<Inner> {}

#[derive(Debug, Clone, Copy)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
pub struct UncheckedBind<Query, Value, ST> {
    query: Query,
    value: Value,
    _marker: PhantomData<ST>,
}

impl<Query, Value, ST> UncheckedBind<Query, Value, ST> {
    pub fn new(query: Query, value: Value) -> Self {
        UncheckedBind {
            query,
            value,
            _marker: PhantomData,
        }
    }

    pub fn bind<ST2, Value2>(self, value: Value2) -> UncheckedBind<Self, Value2, ST2> {
        UncheckedBind::new(self, value)
    }

    pub fn into_boxed<'f, DB: Backend>(self) -> BoxedSqlQuery<'f, DB, Self> {
        BoxedSqlQuery::new(self)
    }

    pub fn sql<T: Into<String>>(self, sql: T) -> SqlQuery<Self> {
        SqlQuery::new(self, sql.into())
    }
}

impl<Query, Value, ST> QueryId for UncheckedBind<Query, Value, ST>
where
    Query: QueryId,
    ST: QueryId,
{
    type QueryId = UncheckedBind<Query::QueryId, (), ST::QueryId>;

    const HAS_STATIC_QUERY_ID: bool = Query::HAS_STATIC_QUERY_ID && ST::HAS_STATIC_QUERY_ID;
}

impl<Query, Value, ST, DB> QueryFragment<DB> for UncheckedBind<Query, Value, ST>
where
    DB: Backend + HasSqlType<ST>,
    Query: QueryFragment<DB>,
    Value: ToSql<ST, DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        self.query.walk_ast(out.reborrow())?;
        out.push_bind_param_value_only(&self.value)?;
        Ok(())
    }
}

impl<Conn, Query, Value, ST, T> LoadQuery<Conn, T> for UncheckedBind<Query, Value, ST>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend> + QueryId,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Conn, Query, Value, ST> RunQueryDsl<Conn> for UncheckedBind<Query, Value, ST> {}

#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
/// See [`SqlQuery::into_boxed`].
///
/// [`SqlQuery::into_boxed`]: ../struct.SqlQuery.html#method.into_boxed
#[allow(missing_debug_implementations)]
pub struct BoxedSqlQuery<'f, DB: Backend, Query> {
    query: Query,
    sql: String,
    binds: Vec<Box<dyn Fn(AstPass<DB>) -> QueryResult<()> + 'f>>,
}

impl<'f, DB: Backend, Query> BoxedSqlQuery<'f, DB, Query> {
    pub(crate) fn new(query: Query) -> Self {
        BoxedSqlQuery {
            query,
            sql: "".to_string(),
            binds: vec![],
        }
    }

    /// See [`SqlQuery::bind`].
    ///
    /// [`SqlQuery::bind`]: ../struct.SqlQuery.html#method.bind
    pub fn bind<BindSt, Value>(mut self, b: Value) -> Self
    where
        DB: HasSqlType<BindSt>,
        Value: ToSql<BindSt, DB> + 'f,
    {
        self.binds
            .push(Box::new(move |mut out| out.push_bind_param_value_only(&b)));
        self
    }

    /// See [`SqlQuery::sql`].
    ///
    /// [`SqlQuery::sql`]: ../struct.SqlQuery.html#method.sql
    pub fn sql<T: AsRef<str>>(mut self, sql: T) -> Self {
        self.sql += sql.as_ref();
        self
    }
}

impl<DB, Query> QueryFragment<DB> for BoxedSqlQuery<'_, DB, Query>
where
    DB: Backend,
    Query: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();
        self.query.walk_ast(out.reborrow())?;
        out.push_sql(&self.sql);

        for b in &self.binds {
            b(out.reborrow())?;
        }
        Ok(())
    }
}

impl<DB: Backend, Query> QueryId for BoxedSqlQuery<'_, DB, Query> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<Conn, T, Query> LoadQuery<Conn, T> for BoxedSqlQuery<'_, Conn::Backend, Query>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend> + QueryId,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Conn: Connection, Query> RunQueryDsl<Conn> for BoxedSqlQuery<'_, Conn::Backend, Query> {}
<commit_msg>Fix broken links<commit_after>use std::marker::PhantomData;

use backend::Backend;
use connection::Connection;
use deserialize::QueryableByName;
use query_builder::{AstPass, QueryFragment, QueryId};
use query_dsl::{LoadQuery, RunQueryDsl};
use result::QueryResult;
use serialize::ToSql;
use sql_types::HasSqlType;

#[derive(Debug, Clone)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
/// The return value of `sql_query`.
///
/// Unlike most queries in Diesel, `SqlQuery` loads its data by column name,
/// rather than by index. This means that you cannot deserialize this query into
/// a tuple, and any structs used must implement `QueryableByName`.
///
/// See [`sql_query`](../fn.sql_query.html) for examples.
pub struct SqlQuery<Inner = ()> {
    inner: Inner,
    query: String,
}

impl<Inner> SqlQuery<Inner> {
    pub(crate) fn new(inner: Inner, query: String) -> Self {
        SqlQuery { inner, query }
    }

    /// Bind a value for use with this SQL query.
    ///
    /// # Safety
    ///
    /// This function should be used with care, as Diesel cannot validate that
    /// the value is of the right type nor can it validate that you have passed
    /// the correct number of parameters.
    ///
    /// # Example
    ///
    /// ```
    /// # #[macro_use] extern crate diesel;
    /// # include!("../doctest_setup.rs");
    /// #
    /// # use schema::users;
    /// #
    /// # #[derive(QueryableByName, Debug, PartialEq)]
    /// # #[table_name="users"]
    /// # struct User {
    /// #     id: i32,
    /// #     name: String,
    /// # }
    /// #
    /// # fn main() {
    /// #     use diesel::sql_query;
    /// #     use diesel::sql_types::{Integer, Text};
    /// #
    /// #     let connection = establish_connection();
    /// #     diesel::insert_into(users::table)
    /// #         .values(users::name.eq("Jim"))
    /// #         .execute(&connection).unwrap();
    /// # #[cfg(feature = "postgres")]
    /// # let users = sql_query("SELECT * FROM users WHERE id > $1 AND name != $2");
    /// # #[cfg(not(feature = "postgres"))]
    /// let users = sql_query("SELECT * FROM users WHERE id > ? AND name <> ?")
    /// # ;
    /// # let users = users
    ///     .bind::<Integer, _>(1)
    ///     .bind::<Text, _>("Tess")
    ///     .get_results(&connection);
    /// let expected_users = vec![
    ///     User { id: 3, name: "Jim".into() },
    /// ];
    /// assert_eq!(Ok(expected_users), users);
    /// # }
    /// ```
    pub fn bind<ST, Value>(self, value: Value) -> UncheckedBind<Self, Value, ST> {
        UncheckedBind::new(self, value)
    }

    /// Internally boxes future calls on `bind` and `sql` so that they don't
    /// change the type.
    ///
    /// This allows doing things you otherwise couldn't do, e.g. `bind`ing in a
    /// loop.
    pub fn into_boxed<'f, DB: Backend>(self) -> BoxedSqlQuery<'f, DB, Self> {
        BoxedSqlQuery::new(self)
    }

    /// Appends a piece of SQL code at the end.
    pub fn sql<T: AsRef<str>>(mut self, sql: T) -> Self {
        self.query += sql.as_ref();
        self
    }
}

impl<DB, Inner> QueryFragment<DB> for SqlQuery<Inner>
where
    DB: Backend,
    Inner: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();
        self.inner.walk_ast(out.reborrow())?;
        out.push_sql(&self.query);
        Ok(())
    }
}

impl<Inner> QueryId for SqlQuery<Inner> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<Inner, Conn, T> LoadQuery<Conn, T> for SqlQuery<Inner>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend>,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Inner, Conn> RunQueryDsl<Conn> for SqlQuery<Inner> {}

#[derive(Debug, Clone, Copy)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
pub struct UncheckedBind<Query, Value, ST> {
    query: Query,
    value: Value,
    _marker: PhantomData<ST>,
}

impl<Query, Value, ST> UncheckedBind<Query, Value, ST> {
    pub fn new(query: Query, value: Value) -> Self {
        UncheckedBind {
            query,
            value,
            _marker: PhantomData,
        }
    }

    pub fn bind<ST2, Value2>(self, value: Value2) -> UncheckedBind<Self, Value2, ST2> {
        UncheckedBind::new(self, value)
    }

    pub fn into_boxed<'f, DB: Backend>(self) -> BoxedSqlQuery<'f, DB, Self> {
        BoxedSqlQuery::new(self)
    }

    pub fn sql<T: Into<String>>(self, sql: T) -> SqlQuery<Self> {
        SqlQuery::new(self, sql.into())
    }
}

impl<Query, Value, ST> QueryId for UncheckedBind<Query, Value, ST>
where
    Query: QueryId,
    ST: QueryId,
{
    type QueryId = UncheckedBind<Query::QueryId, (), ST::QueryId>;

    const HAS_STATIC_QUERY_ID: bool = Query::HAS_STATIC_QUERY_ID && ST::HAS_STATIC_QUERY_ID;
}

impl<Query, Value, ST, DB> QueryFragment<DB> for UncheckedBind<Query, Value, ST>
where
    DB: Backend + HasSqlType<ST>,
    Query: QueryFragment<DB>,
    Value: ToSql<ST, DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        self.query.walk_ast(out.reborrow())?;
        out.push_bind_param_value_only(&self.value)?;
        Ok(())
    }
}

impl<Conn, Query, Value, ST, T> LoadQuery<Conn, T> for UncheckedBind<Query, Value, ST>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend> + QueryId,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Conn, Query, Value, ST> RunQueryDsl<Conn> for UncheckedBind<Query, Value, ST> {}

#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
/// See [`SqlQuery::into_boxed`].
///
/// [`SqlQuery::into_boxed`]: ./struct.SqlQuery.html#method.into_boxed
#[allow(missing_debug_implementations)]
pub struct BoxedSqlQuery<'f, DB: Backend, Query> {
    query: Query,
    sql: String,
    binds: Vec<Box<dyn Fn(AstPass<DB>) -> QueryResult<()> + 'f>>,
}

impl<'f, DB: Backend, Query> BoxedSqlQuery<'f, DB, Query> {
    pub(crate) fn new(query: Query) -> Self {
        BoxedSqlQuery {
            query,
            sql: "".to_string(),
            binds: vec![],
        }
    }

    /// See [`SqlQuery::bind`].
    ///
    /// [`SqlQuery::bind`]: ./struct.SqlQuery.html#method.bind
    pub fn bind<BindSt, Value>(mut self, b: Value) -> Self
    where
        DB: HasSqlType<BindSt>,
        Value: ToSql<BindSt, DB> + 'f,
    {
        self.binds
            .push(Box::new(move |mut out| out.push_bind_param_value_only(&b)));
        self
    }

    /// See [`SqlQuery::sql`].
    ///
    /// [`SqlQuery::sql`]: ./struct.SqlQuery.html#method.sql
    pub fn sql<T: AsRef<str>>(mut self, sql: T) -> Self {
        self.sql += sql.as_ref();
        self
    }
}

impl<DB, Query> QueryFragment<DB> for BoxedSqlQuery<'_, DB, Query>
where
    DB: Backend,
    Query: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();
        self.query.walk_ast(out.reborrow())?;
        out.push_sql(&self.sql);

        for b in &self.binds {
            b(out.reborrow())?;
        }
        Ok(())
    }
}

impl<DB: Backend, Query> QueryId for BoxedSqlQuery<'_, DB, Query> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<Conn, T, Query> LoadQuery<Conn, T> for BoxedSqlQuery<'_, Conn::Backend, Query>
where
    Conn: Connection,
    T: QueryableByName<Conn::Backend>,
    Self: QueryFragment<Conn::Backend> + QueryId,
{
    fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
        conn.query_by_name(&self)
    }
}

impl<Conn: Connection, Query> RunQueryDsl<Conn> for BoxedSqlQuery<'_, Conn::Backend, Query> {}
<|endoftext|>