<commit_before>use prolog::ast::*;
use prolog::codegen::*;
use prolog::prolog_parser::*;
use prolog::machine::*;

use termion::raw::IntoRawMode;
use termion::input::TermRead;
use termion::event::Key;

use std::io::{Write, stdin, stdout};
use std::fmt;

impl fmt::Display for Constant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Constant::Atom(ref atom) =>
                write!(f, "{}", atom),
            &Constant::EmptyList =>
                write!(f, "[]")
        }
    }
}

impl fmt::Display for FactInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &FactInstruction::GetConstant(Level::Shallow, ref constant, ref r) =>
                write!(f, "get_constant {}, A{}", constant, r.reg_num()),
            &FactInstruction::GetConstant(Level::Deep, ref constant, ref r) =>
                write!(f, "get_constant {}, {}", constant, r),
            &FactInstruction::GetList(Level::Shallow, ref r) =>
                write!(f, "get_list A{}", r.reg_num()),
            &FactInstruction::GetList(Level::Deep, ref r) =>
                write!(f, "get_list {}", r),
            &FactInstruction::GetStructure(Level::Deep, ref name, ref arity, ref r) =>
                write!(f, "get_structure {}/{}, {}", name, arity, r),
            &FactInstruction::GetStructure(Level::Shallow, ref name, ref arity, ref r) =>
                write!(f, "get_structure {}/{}, A{}", name, arity, r.reg_num()),
            &FactInstruction::GetValue(ref x, ref a) =>
                write!(f, "get_value {}, A{}", x, a),
            &FactInstruction::GetVariable(ref x, ref a) =>
                write!(f, "get_variable {}, A{}", x, a),
            &FactInstruction::UnifyConstant(ref constant) =>
                write!(f, "unify_constant {}", constant),
            &FactInstruction::UnifyVariable(ref r) =>
                write!(f, "unify_variable {}", r),
            &FactInstruction::UnifyLocalValue(ref r) =>
                write!(f, "unify_local_value {}", r),
            &FactInstruction::UnifyValue(ref r) =>
                write!(f, "unify_value {}", r),
            &FactInstruction::UnifyVoid(n) =>
                write!(f, "unify_void {}", n)
        }
    }
}

impl fmt::Display for QueryInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
                write!(f, "put_constant {}, A{}", constant, r.reg_num()),
            &QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) =>
                write!(f, "put_constant {}, {}", constant, r),
            &QueryInstruction::PutList(Level::Shallow, ref r) =>
                write!(f, "put_list A{}", r.reg_num()),
            &QueryInstruction::PutList(Level::Deep, ref r) =>
                write!(f, "put_list {}", r),
            &QueryInstruction::PutStructure(Level::Deep, ref name, ref arity, ref r) =>
                write!(f, "put_structure {}/{}, {}", name, arity, r),
            &QueryInstruction::PutStructure(Level::Shallow, ref name, ref arity, ref r) =>
                write!(f, "put_structure {}/{}, A{}", name, arity, r.reg_num()),
            &QueryInstruction::PutUnsafeValue(y, a) =>
                write!(f, "put_unsafe_value Y{}, A{}", y, a),
            &QueryInstruction::PutValue(ref x, ref a) =>
                write!(f, "put_value {}, A{}", x, a),
            &QueryInstruction::PutVariable(ref x, ref a) =>
                write!(f, "put_variable {}, A{}", x, a),
            &QueryInstruction::SetConstant(ref constant) =>
                write!(f, "set_constant {}", constant),
            &QueryInstruction::SetLocalValue(ref r) =>
                write!(f, "set_local_value {}", r),
            &QueryInstruction::SetVariable(ref r) =>
                write!(f, "set_variable {}", r),
            &QueryInstruction::SetValue(ref r) =>
                write!(f, "set_value {}", r),
            &QueryInstruction::SetVoid(n) =>
                write!(f, "set_void {}", n)
        }
    }
}

impl fmt::Display for ControlInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ControlInstruction::Allocate(num_cells) =>
                write!(f, "allocate {}", num_cells),
            &ControlInstruction::Call(ref name, arity, pvs) =>
                write!(f, "call {}/{}, {}", name, arity, pvs),
            &ControlInstruction::Deallocate =>
                write!(f, "deallocate"),
            &ControlInstruction::Execute(ref name, arity) =>
                write!(f, "execute {}/{}", name, arity),
            &ControlInstruction::Proceed =>
                write!(f, "proceed")
        }
    }
}

impl fmt::Display for ChoiceInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ChoiceInstruction::TryMeElse(offset) =>
                write!(f, "try_me_else {}", offset),
            &ChoiceInstruction::RetryMeElse(offset) =>
                write!(f, "retry_me_else {}", offset),
            &ChoiceInstruction::TrustMe =>
                write!(f, "trust_me")
        }
    }
}

impl fmt::Display for Level {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Level::Shallow => write!(f, "A"),
            &Level::Deep => write!(f, "X")
        }
    }
}

impl fmt::Display for VarReg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg),
            &VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg),
            &VarReg::ArgAndNorm(RegType::Perm(reg), arg) =>
                write!(f, "Y{} A{}", reg, arg),
            &VarReg::ArgAndNorm(RegType::Temp(reg), arg) =>
                write!(f, "X{} A{}", reg, arg)
        }
    }
}

impl fmt::Display for RegType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &RegType::Perm(val) => write!(f, "Y{}", val),
            &RegType::Temp(val) => write!(f, "X{}", val)
        }
    }
}

fn is_consistent(predicate: &Vec<PredicateClause>) -> bool {
    let name  = predicate.first().unwrap().name();
    let arity = predicate.first().unwrap().arity();

    for clause in predicate.iter().skip(1) {
        if !(name == clause.name() && arity == clause.arity()) {
            return false;
        }
    }

    true
}

#[allow(dead_code)]
pub fn print_code(code: &Code) {
    for clause in code {
        match clause {
            &Line::Fact(ref fact) =>
                for fact_instr in fact {
                    println!("{}", fact_instr);
                },
            &Line::Choice(ref choice) =>
                println!("{}", choice),
            &Line::Control(ref control) =>
                println!("{}", control),
            &Line::Query(ref query) =>
                for query_instr in query {
                    println!("{}", query_instr);
                }
        }
    }
}

pub fn read() -> String {
    let _ = stdout().flush();

    let mut buffer = String::new();
    let mut result = String::new();

    let stdin = stdin();
    stdin.read_line(&mut buffer).unwrap();

    if &*buffer.trim() == ":{" {
        buffer.clear();

        stdin.read_line(&mut buffer).unwrap();

        while &*buffer.trim() != "}:" {
            result += buffer.as_str();
            buffer.clear();
            stdin.read_line(&mut buffer).unwrap();
        }
    } else {
        result = buffer;
    }

    result
}

pub fn eval(wam: &mut Machine, buffer: &str) -> EvalResult
{
    let result = parse_TopLevel(buffer);
    let mut cg = CodeGenerator::new();

    match &result {
        &Ok(TopLevel::Predicate(ref clauses)) => {
            if is_consistent(clauses) {
                let compiled_pred = cg.compile_predicate(clauses);
                print_code(&compiled_pred);
                wam.add_predicate(clauses, compiled_pred);

                EvalResult::EntrySuccess
            } else {
                let msg = r"Error: predicate is inconsistent.
Each predicate must have the same name and arity.";

                println!("{}", msg);
                EvalResult::EntryFailure
            }
        },
        &Ok(TopLevel::Fact(ref fact)) => {
            let compiled_fact = cg.compile_fact(&fact);
            print_code(&compiled_fact);
            wam.add_fact(fact, compiled_fact);
            EvalResult::EntrySuccess
        },
        &Ok(TopLevel::Rule(ref rule)) => {
            let compiled_rule = cg.compile_rule(&rule);
            print_code(&compiled_rule);
            wam.add_rule(rule, compiled_rule);
            EvalResult::EntrySuccess
        },
        &Ok(TopLevel::Query(ref query)) => {
            let compiled_query = cg.compile_query(&query);
            wam.run_query(compiled_query, &cg)
        },
        &Err(_) => {
            println!("Grammatical error of some kind!");
            EvalResult::EntryFailure
        }
    }
}

pub fn print(wam: &mut Machine, result: EvalResult) {
    match result {
        EvalResult::InitialQuerySuccess(heap_locs) => {
            println!("yes");

            if heap_locs.is_empty() {
                return;
            }

            'outer: loop {
                let mut result = EvalResult::QueryFailure;
                let bindings = wam.heap_view(&heap_locs);

                let stdin  = stdin();
                let mut stdout = stdout().into_raw_mode().unwrap();

                write!(stdout, "{}\n\r", bindings).unwrap();
                stdout.flush().unwrap();

                if !wam.or_stack_is_empty() {
                    write!(stdout, "Press ; to continue or . to abort.\n\r").unwrap();
                    stdout.flush().unwrap();

                    for c in stdin.keys() {
                        match c.unwrap() {
                            Key::Char(';') => {
                                result = wam.continue_query();
                                break;
                            },
                            Key::Char('.') =>
                                break 'outer,
                            _ => {}
                        }
                    };

                    if let &EvalResult::QueryFailure = &result {
                        write!(stdout, "no\n\r").unwrap();
                        stdout.flush().unwrap();
                        break;
                    }
                } else {
                    break;
                }
            }
        },
        EvalResult::QueryFailure => println!("no"),
        _ => {}
    };
}
<commit_msg>remove print debug<commit_after>use prolog::ast::*;
use prolog::codegen::*;
use prolog::prolog_parser::*;
use prolog::machine::*;

use termion::raw::IntoRawMode;
use termion::input::TermRead;
use termion::event::Key;

use std::io::{Write, stdin, stdout};
use std::fmt;

impl fmt::Display for Constant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Constant::Atom(ref atom) =>
                write!(f, "{}", atom),
            &Constant::EmptyList =>
                write!(f, "[]")
        }
    }
}

impl fmt::Display for FactInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &FactInstruction::GetConstant(Level::Shallow, ref constant, ref r) =>
                write!(f, "get_constant {}, A{}", constant, r.reg_num()),
            &FactInstruction::GetConstant(Level::Deep, ref constant, ref r) =>
                write!(f, "get_constant {}, {}", constant, r),
            &FactInstruction::GetList(Level::Shallow, ref r) =>
                write!(f, "get_list A{}", r.reg_num()),
            &FactInstruction::GetList(Level::Deep, ref r) =>
                write!(f, "get_list {}", r),
            &FactInstruction::GetStructure(Level::Deep, ref name, ref arity, ref r) =>
                write!(f, "get_structure {}/{}, {}", name, arity, r),
            &FactInstruction::GetStructure(Level::Shallow, ref name, ref arity, ref r) =>
                write!(f, "get_structure {}/{}, A{}", name, arity, r.reg_num()),
            &FactInstruction::GetValue(ref x, ref a) =>
                write!(f, "get_value {}, A{}", x, a),
            &FactInstruction::GetVariable(ref x, ref a) =>
                write!(f, "get_variable {}, A{}", x, a),
            &FactInstruction::UnifyConstant(ref constant) =>
                write!(f, "unify_constant {}", constant),
            &FactInstruction::UnifyVariable(ref r) =>
                write!(f, "unify_variable {}", r),
            &FactInstruction::UnifyLocalValue(ref r) =>
                write!(f, "unify_local_value {}", r),
            &FactInstruction::UnifyValue(ref r) =>
                write!(f, "unify_value {}", r),
            &FactInstruction::UnifyVoid(n) =>
                write!(f, "unify_void {}", n)
        }
    }
}

impl fmt::Display for QueryInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
                write!(f, "put_constant {}, A{}", constant, r.reg_num()),
            &QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) =>
                write!(f, "put_constant {}, {}", constant, r),
            &QueryInstruction::PutList(Level::Shallow, ref r) =>
                write!(f, "put_list A{}", r.reg_num()),
            &QueryInstruction::PutList(Level::Deep, ref r) =>
                write!(f, "put_list {}", r),
            &QueryInstruction::PutStructure(Level::Deep, ref name, ref arity, ref r) =>
                write!(f, "put_structure {}/{}, {}", name, arity, r),
            &QueryInstruction::PutStructure(Level::Shallow, ref name, ref arity, ref r) =>
                write!(f, "put_structure {}/{}, A{}", name, arity, r.reg_num()),
            &QueryInstruction::PutUnsafeValue(y, a) =>
                write!(f, "put_unsafe_value Y{}, A{}", y, a),
            &QueryInstruction::PutValue(ref x, ref a) =>
                write!(f, "put_value {}, A{}", x, a),
            &QueryInstruction::PutVariable(ref x, ref a) =>
                write!(f, "put_variable {}, A{}", x, a),
            &QueryInstruction::SetConstant(ref constant) =>
                write!(f, "set_constant {}", constant),
            &QueryInstruction::SetLocalValue(ref r) =>
                write!(f, "set_local_value {}", r),
            &QueryInstruction::SetVariable(ref r) =>
                write!(f, "set_variable {}", r),
            &QueryInstruction::SetValue(ref r) =>
                write!(f, "set_value {}", r),
            &QueryInstruction::SetVoid(n) =>
                write!(f, "set_void {}", n)
        }
    }
}

impl fmt::Display for ControlInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ControlInstruction::Allocate(num_cells) =>
                write!(f, "allocate {}", num_cells),
            &ControlInstruction::Call(ref name, arity, pvs) =>
                write!(f, "call {}/{}, {}", name, arity, pvs),
            &ControlInstruction::Deallocate =>
                write!(f, "deallocate"),
            &ControlInstruction::Execute(ref name, arity) =>
                write!(f, "execute {}/{}", name, arity),
            &ControlInstruction::Proceed =>
                write!(f, "proceed")
        }
    }
}

impl fmt::Display for ChoiceInstruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ChoiceInstruction::TryMeElse(offset) =>
                write!(f, "try_me_else {}", offset),
            &ChoiceInstruction::RetryMeElse(offset) =>
                write!(f, "retry_me_else {}", offset),
            &ChoiceInstruction::TrustMe =>
                write!(f, "trust_me")
        }
    }
}

impl fmt::Display for Level {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Level::Shallow => write!(f, "A"),
            &Level::Deep => write!(f, "X")
        }
    }
}

impl fmt::Display for VarReg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg),
            &VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg),
            &VarReg::ArgAndNorm(RegType::Perm(reg), arg) =>
                write!(f, "Y{} A{}", reg, arg),
            &VarReg::ArgAndNorm(RegType::Temp(reg), arg) =>
                write!(f, "X{} A{}", reg, arg)
        }
    }
}

impl fmt::Display for RegType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &RegType::Perm(val) => write!(f, "Y{}", val),
            &RegType::Temp(val) => write!(f, "X{}", val)
        }
    }
}

fn is_consistent(predicate: &Vec<PredicateClause>) -> bool {
    let name  = predicate.first().unwrap().name();
    let arity = predicate.first().unwrap().arity();

    for clause in predicate.iter().skip(1) {
        if !(name == clause.name() && arity == clause.arity()) {
            return false;
        }
    }

    true
}

#[allow(dead_code)]
pub fn print_code(code: &Code) {
    for clause in code {
        match clause {
            &Line::Fact(ref fact) =>
                for fact_instr in fact {
                    println!("{}", fact_instr);
                },
            &Line::Choice(ref choice) =>
                println!("{}", choice),
            &Line::Control(ref control) =>
                println!("{}", control),
            &Line::Query(ref query) =>
                for query_instr in query {
                    println!("{}", query_instr);
                }
        }
    }
}

pub fn read() -> String {
    let _ = stdout().flush();

    let mut buffer = String::new();
    let mut result = String::new();

    let stdin = stdin();
    stdin.read_line(&mut buffer).unwrap();

    if &*buffer.trim() == ":{" {
        buffer.clear();

        stdin.read_line(&mut buffer).unwrap();

        while &*buffer.trim() != "}:" {
            result += buffer.as_str();
            buffer.clear();
            stdin.read_line(&mut buffer).unwrap();
        }
    } else {
        result = buffer;
    }

    result
}

pub fn eval(wam: &mut Machine, buffer: &str) -> EvalResult
{
    let result = parse_TopLevel(buffer);
    let mut cg = CodeGenerator::new();

    match &result {
        &Ok(TopLevel::Predicate(ref clauses)) => {
            if is_consistent(clauses) {
                let compiled_pred = cg.compile_predicate(clauses);
                wam.add_predicate(clauses, compiled_pred);

                EvalResult::EntrySuccess
            } else {
                let msg = r"Error: predicate is inconsistent.
Each predicate must have the same name and arity.";

                println!("{}", msg);
                EvalResult::EntryFailure
            }
        },
        &Ok(TopLevel::Fact(ref fact)) => {
            let compiled_fact = cg.compile_fact(&fact);
            wam.add_fact(fact, compiled_fact);
            EvalResult::EntrySuccess
        },
        &Ok(TopLevel::Rule(ref rule)) => {
            let compiled_rule = cg.compile_rule(&rule);
            wam.add_rule(rule, compiled_rule);
            EvalResult::EntrySuccess
        },
        &Ok(TopLevel::Query(ref query)) => {
            let compiled_query = cg.compile_query(&query);
            wam.run_query(compiled_query, &cg)
        },
        &Err(_) => {
            println!("Grammatical error of some kind!");
            EvalResult::EntryFailure
        }
    }
}

pub fn print(wam: &mut Machine, result: EvalResult) {
    match result {
        EvalResult::InitialQuerySuccess(heap_locs) => {
            println!("yes");

            if heap_locs.is_empty() {
                return;
            }

            'outer: loop {
                let mut result = EvalResult::QueryFailure;
                let bindings = wam.heap_view(&heap_locs);

                let stdin  = stdin();
                let mut stdout = stdout().into_raw_mode().unwrap();

                write!(stdout, "{}\n\r", bindings).unwrap();
                stdout.flush().unwrap();

                if !wam.or_stack_is_empty() {
                    write!(stdout, "Press ; to continue or . to abort.\n\r").unwrap();
                    stdout.flush().unwrap();

                    for c in stdin.keys() {
                        match c.unwrap() {
                            Key::Char(';') => {
                                result = wam.continue_query();
                                break;
                            },
                            Key::Char('.') =>
                                break 'outer,
                            _ => {}
                        }
                    };

                    if let &EvalResult::QueryFailure = &result {
                        write!(stdout, "no\n\r").unwrap();
                        stdout.flush().unwrap();
                        break;
                    }
                } else {
                    break;
                }
            }
        },
        EvalResult::QueryFailure => println!("no"),
        _ => {}
    };
}
<|endoftext|>


<commit_before>use ::{Points, Value};

/// Resolve the points to line protocol format
pub fn line_serialization(points: Points) -> String {
    let mut line = Vec::new();
    for point in points.point {
        line.push(point.measurement);

        for (tag, value) in point.tags.iter() {
            line.push(",".to_string());
            line.push(tag.to_string());
            line.push("=".to_string());

            match value {
                &Value::String(ref s) => line.push(s.to_string()),
                &Value::Float(ref f) => line.push(f.to_string()),
                &Value::Integer(ref i) => line.push(i.to_string()),
                &Value::Boolean(b) => line.push({ if b { "true".to_string() } else { "false".to_string() } })
            }
        }

        let mut was_first = true;

        for (field, value) in point.fields.iter() {
            line.push({
                if was_first {
                    was_first = false;
                    " "
                } else { "," }
            }.to_string());
            line.push(field.to_string());
            line.push("=".to_string());

            match value {
                &Value::String(ref s) => line.push(s.to_string()),
                &Value::Float(ref f) => line.push(f.to_string()),
                &Value::Integer(ref i) => line.push(i.to_string()),
                &Value::Boolean(b) => line.push({ if b { "true".to_string() } else { "false".to_string() } })
            }
        }

        match point.timestamp {
            Some(t) => {
                line.push(" ".to_string());
                line.push(t.to_string());
            }
            _ => {}
        }

        line.push("\n".to_string())
    }

    line.join("")
}

#[inline]
pub fn quote_ident(value: &str) -> String {
    format!("\"{}\"", value.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n"))
}

#[inline]
pub fn quote_literal(value: &str) -> String {
    format!("'{}'", value.replace("\\", "\\\\").replace("'", "\\'"))
}

#[inline]
pub fn conversion(value: String) -> String {
    value.replace("\'", "").replace("\"", "").replace("\\", "").trim().to_string()
}

#[cfg(test)]
mod test {
    use super::*;
    use ::{Point, Points};

    #[test]
    fn line_serialization_test() {
        let mut point = Point::new("test");
        point.add_field("somefield", Value::Integer(65));
        point.add_tag("sometag", Value::Boolean(false));
        let points = Points::new(point);

        assert_eq!(line_serialization(points), "test,sometag=false somefield=65\n")
    }

    #[test]
    fn quote_ident_test() {
        assert_eq!(quote_ident("root"), "\"root\"")
    }

    #[test]
    fn quote_literal_test(){
        assert_eq!(quote_literal("root"), "\'root\'")
    }
}
<commit_msg>Proper escaping of special characters<commit_after>use ::{Points, Value};

/// Resolve the points to line protocol format
pub fn line_serialization(points: Points) -> String {
    let mut line = Vec::new();
    for point in points.point {
        line.push(escape_measurement(point.measurement));

        for (tag, value) in point.tags.iter() {
            line.push(",".to_string());
            line.push(escape_keys_and_tags(tag.to_string()));
            line.push("=".to_string());

            match value {
                &Value::String(ref s) => line.push(escape_keys_and_tags(s.to_string())),
                &Value::Float(ref f) => line.push(f.to_string()),
                &Value::Integer(ref i) => line.push(i.to_string()),
                &Value::Boolean(b) => line.push({ if b { "true".to_string() } else { "false".to_string() } })
            }
        }

        let mut was_first = true;

        for (field, value) in point.fields.iter() {
            line.push({
                if was_first {
                    was_first = false;
                    " "
                } else { "," }
            }.to_string());
            line.push(escape_keys_and_tags(field.to_string()));
            line.push("=".to_string());

            match value {
                &Value::String(ref s) => line.push(escape_string_field_value(s.to_string())),
                &Value::Float(ref f) => line.push(f.to_string()),
                &Value::Integer(ref i) => line.push(i.to_string()),
                &Value::Boolean(b) => line.push({ if b { "true".to_string() } else { "false".to_string() } })
            }
        }

        match point.timestamp {
            Some(t) => {
                line.push(" ".to_string());
                line.push(t.to_string());
            }
            _ => {}
        }

        line.push("\n".to_string())
    }

    line.join("")
}

#[inline]
pub fn quote_ident(value: &str) -> String {
    format!("\"{}\"", value.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n"))
}

#[inline]
pub fn quote_literal(value: &str) -> String {
    format!("'{}'", value.replace("\\", "\\\\").replace("'", "\\'"))
}

#[inline]
pub fn conversion(value: String) -> String {
    value.replace("\'", "").replace("\"", "").replace("\\", "").trim().to_string()
}

#[inline]
fn escape_keys_and_tags(value: String) -> String {
    value.replace(",", "\\,").replace("=", "\\=").replace(" ", "\\ ")
}

#[inline]
fn escape_measurement(value: String) -> String {
    value.replace(",", "\\,").replace(" ", "\\ ")
}

#[inline]
fn escape_string_field_value(value: String) -> String {
    value.replace("\"", "\\\"")
}

#[cfg(test)]
mod test {
    use super::*;
    use ::{Point, Points};

    #[test]
    fn line_serialization_test() {
        let mut point = Point::new("test");
        point.add_field("somefield", Value::Integer(65));
        point.add_tag("sometag", Value::Boolean(false));
        let points = Points::new(point);

        assert_eq!(line_serialization(points), "test,sometag=false somefield=65\n")
    }

    #[test]
    fn escape_keys_and_tags_test() {
        assert_eq!(escape_keys_and_tags(String::from("foo, hello=world")) , "foo\\,\\ hello\\=world")
    }

    #[test]
    fn escape_measurement_test() {
        assert_eq!(escape_measurement(String::from("foo, hello")) , "foo\\,\\ hello")
    }

    #[test]
    fn escape_string_field_value_test() {
        assert_eq!(escape_string_field_value(String::from("\"foo")) , "\\\"foo")
    }

    #[test]
    fn quote_ident_test() {
        assert_eq!(quote_ident("root"), "\"root\"")
    }

    #[test]
    fn quote_literal_test(){
        assert_eq!(quote_literal("root"), "\'root\'")
    }
}
<|endoftext|>


<commit_before>//! redis-rs is a rust implementation of a Redis client library.  It exposes
//! a general purpose interface to Redis and also provides specific helpers for
//! commonly used functionality.
//!
//! # Basic Operation
//!
//! To open a connection you need to create a client and then to fetch a
//! connection from it.  In the future there will be a connection pool for
//! those, currently each connection is separate and not pooled.
//!
//! Queries are then performed through the `execute` and `query` methods.
//!
//! ```rust,no_run
//! extern crate redis;
//!
//! fn main() {
//!     let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//!     let con = client.get_connection().unwrap();
//!     redis::cmd("SET").arg("my_key").arg(42i).execute(&con);
//!     assert_eq!(redis::cmd("GET").arg("my_key").query(&con), Ok(42i));
//! }
//! ```
//!
//! ## Type Conversions
//!
//! Because redis inherently is mostly type-less and the protocol is not
//! exactly friendly to developers, this library provides flexible support
//! for casting values to the intended results.  This is driven through the
//! `FromRedisValue` and `ToRedisArgs` traits.
//!
//! The `arg` method of the command will accept a wide range of types through
//! the `ToRedisArgs` trait and the `query` method of a command can convert the
//! value to what you expect the function to return through the `FromRedisValue`
//! trait.  This is quite flexible and allows vectors, tuples, hashsets, hashmaps
//! as well as optional values:
//!
//! ```rust,no_run
//! # use std::collections::{HashMap, HashSet};
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let count : i32 = redis::cmd("GET").arg("my_counter").query(&con).unwrap();
//! let count = redis::cmd("GET").arg("my_counter").query(&con).unwrap_or(0i32);
//! let k : Option<String> = redis::cmd("GET").arg("missing_key").query(&con).unwrap();
//! let name : String = redis::cmd("GET").arg("my_name").query(&con).unwrap();
//! let bin : Vec<u8> = redis::cmd("GET").arg("my_binary").query(&con).unwrap();
//! let map : HashMap<String, i32> = redis::cmd("HGETALL").arg("my_hash").query(&con).unwrap();
//! let keys : Vec<String> = redis::cmd("KEYS").query(&con).unwrap();
//! let mems : HashSet<i32> = redis::cmd("SMEMBERS").arg("s").query(&con).unwrap();
//! let (k1, k2) : (String, String) = redis::cmd("MGET").arg("k1").arg("k2").query(&con).unwrap();
//! ```
//!
//! ## Iteration Protocol
//!
//! In addition to sending a single query you iterators are also supported.  When
//! used with regular bulk responses they don't give you much over querying and
//! converting into a vector (both use a vector internally) but they can also
//! be used with `SCAN` like commands in which case iteration will send more
//! queries until the cursor is exhausted:
//!
//! ```rust,no_run
//! # use std::collections::{HashMap, HashSet};
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let mut cmd = redis::cmd("SSCAN");
//! let mut iter : redis::Iter<int> = cmd.arg("my_set").cursor_arg(0).iter(&con).unwrap();
//! for x in iter {
//!     // do something with the item
//! }
//! ```
//!
//! As you can see the cursor argument needs to be defined with `cursor_arg` instead
//! of `arg` so that the library knows which argument needs updating as the
//! query is run for more items.

#![crate_name = "redis"]
#![crate_type = "lib"]
#![license = "BSD"]
#![comment = "Bindings and wrapper functions for redis."]

#![deny(non_camel_case_types)]

#![feature(macro_rules)]
#![feature(default_type_params)]

#![experimental]

extern crate url;
extern crate serialize;

/* public api */
pub use parser::{parse_redis_value, Parser};
pub use client::Client;
pub use connection::Connection;
pub use cmd::{cmd, Cmd, Iter};

#[doc(hidden)]
pub use types::{
    /* low level values */
    Value,
        Nil,
        Int,
        Data,
        Bulk,
        Okay,
        Status,

    /* error and result types */
    Error,
    RedisResult,

    /* error kinds */
    ErrorKind,
        ResponseError,
        TypeError,
        ExecAbortError,
        BusyLoadingError,
        NoScriptError,
        ExtensionError,
        InternalIoError,

    /* utility types */
    InfoDict,

    /* conversion traits */
    FromRedisValue,
    ToRedisArgs,
};

pub mod macros;

mod parser;
mod client;
mod connection;
mod types;
mod cmd;
<commit_msg>Removed unused imports.<commit_after>//! redis-rs is a rust implementation of a Redis client library.  It exposes
//! a general purpose interface to Redis and also provides specific helpers for
//! commonly used functionality.
//!
//! # Basic Operation
//!
//! To open a connection you need to create a client and then to fetch a
//! connection from it.  In the future there will be a connection pool for
//! those, currently each connection is separate and not pooled.
//!
//! Queries are then performed through the `execute` and `query` methods.
//!
//! ```rust,no_run
//! extern crate redis;
//!
//! fn main() {
//!     let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//!     let con = client.get_connection().unwrap();
//!     redis::cmd("SET").arg("my_key").arg(42i).execute(&con);
//!     assert_eq!(redis::cmd("GET").arg("my_key").query(&con), Ok(42i));
//! }
//! ```
//!
//! ## Type Conversions
//!
//! Because redis inherently is mostly type-less and the protocol is not
//! exactly friendly to developers, this library provides flexible support
//! for casting values to the intended results.  This is driven through the
//! `FromRedisValue` and `ToRedisArgs` traits.
//!
//! The `arg` method of the command will accept a wide range of types through
//! the `ToRedisArgs` trait and the `query` method of a command can convert the
//! value to what you expect the function to return through the `FromRedisValue`
//! trait.  This is quite flexible and allows vectors, tuples, hashsets, hashmaps
//! as well as optional values:
//!
//! ```rust,no_run
//! # use std::collections::{HashMap, HashSet};
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let count : i32 = redis::cmd("GET").arg("my_counter").query(&con).unwrap();
//! let count = redis::cmd("GET").arg("my_counter").query(&con).unwrap_or(0i32);
//! let k : Option<String> = redis::cmd("GET").arg("missing_key").query(&con).unwrap();
//! let name : String = redis::cmd("GET").arg("my_name").query(&con).unwrap();
//! let bin : Vec<u8> = redis::cmd("GET").arg("my_binary").query(&con).unwrap();
//! let map : HashMap<String, i32> = redis::cmd("HGETALL").arg("my_hash").query(&con).unwrap();
//! let keys : Vec<String> = redis::cmd("KEYS").query(&con).unwrap();
//! let mems : HashSet<i32> = redis::cmd("SMEMBERS").arg("s").query(&con).unwrap();
//! let (k1, k2) : (String, String) = redis::cmd("MGET").arg("k1").arg("k2").query(&con).unwrap();
//! ```
//!
//! ## Iteration Protocol
//!
//! In addition to sending a single query you iterators are also supported.  When
//! used with regular bulk responses they don't give you much over querying and
//! converting into a vector (both use a vector internally) but they can also
//! be used with `SCAN` like commands in which case iteration will send more
//! queries until the cursor is exhausted:
//!
//! ```rust,no_run
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let mut cmd = redis::cmd("SSCAN");
//! let mut iter : redis::Iter<int> = cmd.arg("my_set").cursor_arg(0).iter(&con).unwrap();
//! for x in iter {
//!     // do something with the item
//! }
//! ```
//!
//! As you can see the cursor argument needs to be defined with `cursor_arg` instead
//! of `arg` so that the library knows which argument needs updating as the
//! query is run for more items.

#![crate_name = "redis"]
#![crate_type = "lib"]
#![license = "BSD"]
#![comment = "Bindings and wrapper functions for redis."]

#![deny(non_camel_case_types)]

#![feature(macro_rules)]
#![feature(default_type_params)]

#![experimental]

extern crate url;
extern crate serialize;

/* public api */
pub use parser::{parse_redis_value, Parser};
pub use client::Client;
pub use connection::Connection;
pub use cmd::{cmd, Cmd, Iter};

#[doc(hidden)]
pub use types::{
    /* low level values */
    Value,
        Nil,
        Int,
        Data,
        Bulk,
        Okay,
        Status,

    /* error and result types */
    Error,
    RedisResult,

    /* error kinds */
    ErrorKind,
        ResponseError,
        TypeError,
        ExecAbortError,
        BusyLoadingError,
        NoScriptError,
        ExtensionError,
        InternalIoError,

    /* utility types */
    InfoDict,

    /* conversion traits */
    FromRedisValue,
    ToRedisArgs,
};

pub mod macros;

mod parser;
mod client;
mod connection;
mod types;
mod cmd;
<|endoftext|>


<commit_before>//! [β-reduction](https://en.wikipedia.org/wiki/Beta_normal_form) for lambda `Term`s

#![allow(dead_code)]

use term::*;
use term::Term::*;
/*
use self::Closure::*;
use self::Expression::*;
use std::collections::VecDeque;

#[derive(Debug, PartialEq, Clone)]
enum Closure {
    Depth(usize),
    TermInEnv(Term, Environment)
}

#[derive(Debug, PartialEq)]
enum Expression {
    Evaluation(Closure),
    Application(Box<Expression>, Term, Environment)
}

type Environment = VecDeque<Closure>;

fn whnf(term: Term, mut env: Environment) -> Expression {
    match term {
        Var(i) => match env.remove(i - 1) {
            Some(Depth(i)) => Evaluation(Depth(i)),
            Some(TermInEnv(t, e)) => whnf(t, e),
            None => unreachable!()
        },
        Abs(t) => Evaluation(TermInEnv(Abs(t), env)),
        App(lhs, rhs) => match whnf(*lhs, env.clone()) { // TODO: try to remove this clone()
            Evaluation(TermInEnv(Abs(lhs2), mut env2)) => {
                env2.push_front(TermInEnv(*rhs, env));
                whnf(*lhs2, env2)
            },
            expr => Application(Box::new(expr), *rhs, env)
        }
    }
}

fn reduce(depth: usize, exp: Expression) -> Term {
    match exp {
        Application(lhs, rhs, env) => app(reduce(depth, *lhs), nf(depth, rhs, env)),
        Evaluation(TermInEnv(Abs(term), mut env)) => {
            env.push_front(Depth(depth));
            abs(nf(depth + 1, *term, env))
        },
        Evaluation(TermInEnv(term, _)) => term,
        Evaluation(Depth(i)) => Var(depth - i)
    }
}

fn nf(depth: usize, term: Term, env: Environment) -> Term {
    reduce(depth, whnf(term, env))
}

/// Returns a term reduced to its normal form. Consumes its argument.
///
/// # Example
///
/// ```
/// use lambda_calculus::booleans::{if_else, tru};
/// use lambda_calculus::arithmetic::{zero, one, succ};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(succ().app(zero())), one());
/// assert_eq!(normalize(if_else().app(tru()).app(one()).app(zero())), one());
/// ```
fn normalize(term: Term) -> Term {
    nf(0, term, VecDeque::new())
}
*/
/// Applies two terms with substitution and variable update, consuming the first one in the process.
///
/// # Example
/// ```
/// use lambda_calculus::reduction::apply;
/// use lambda_calculus::parser::parse;
///
/// let lhs    = parse(&"λλ42(λ13)").unwrap();
/// let rhs    = parse(&"λ51").unwrap();
/// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
///
/// assert_eq!(apply(lhs, &rhs), Ok(result));
/// ```
pub fn apply(mut lhs: Term, rhs: &Term) -> Result<Term, Error> {
    _apply(&mut lhs, rhs, 0);

    lhs.unabs()
}

fn _apply(lhs: &mut Term, rhs: &Term, depth: usize) {
    match *lhs {
        Var(i) => if i == depth {
            *lhs = rhs.clone(); // substitute a top-level variable from lhs with rhs
            update_free_variables(lhs, depth - 1, 0); // update indices of free variables from rhs
        } else if i > depth {
            *lhs = Var(i - 1) // decrement a free variable's index
        },
        Abs(_) => {
            _apply(lhs.unabs_ref_mut().unwrap(), rhs, depth + 1)
        },
        App(_, _) => {
            _apply(lhs.lhs_ref_mut().unwrap(), rhs, depth);
            _apply(lhs.rhs_ref_mut().unwrap(), rhs, depth)
        }
    }
}

fn update_free_variables(term: &mut Term, added_depth: usize, own_depth: usize) {
    match *term {
        Var(i) => if i > own_depth {
            *term = Var(i + added_depth)
        },
        Abs(_) => {
            update_free_variables(term.unabs_ref_mut().unwrap(), added_depth, own_depth + 1)
        },
        App(_, _) => {
            update_free_variables(term.lhs_ref_mut().unwrap(), added_depth, own_depth);
            update_free_variables(term.rhs_ref_mut().unwrap(), added_depth, own_depth)
        }
    }
}

/// Set to `true` to see all the steps of β-reductions. The default is `false`.
pub const SHOW_REDUCTIONS: bool = false;

impl Term {
    /// Applies `self` to another term with substitution and variable update, consuming it
    /// in the process.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::parser::parse;
    ///
    /// let lhs    = parse(&"λλ42(λ13)").unwrap();
    /// let rhs    = parse(&"λ51").unwrap();
    /// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
    ///
    /// assert_eq!(lhs.apply(&rhs), Ok(result));
    /// ```
    pub fn apply(self, rhs: &Term) -> Result<Term, Error> {
        apply(self, rhs)
    }

    /// Reduces an `App`lication by substitution and variable update.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::{app, abs};
    /// use lambda_calculus::term::Term::Var;
    /// use lambda_calculus::arithmetic::zero;
    /// use lambda_calculus::combinators::i;
    ///
    /// assert_eq!(app(i(), zero()).eval(), Ok(abs(abs(Var(1)))));
    /// ```
    pub fn eval(self) -> Result<Term, Error> {
        let (lhs, rhs) = try!(self.unapp());

        apply(lhs, &rhs)
    }

    /// Performs a single normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::succ;
    ///
    /// let mut succ_one = succ().app(1.into());
    /// succ_one.beta_once();
    ///
    /// assert_eq!(succ_one, succ().apply(&1.into()).unwrap());
    /// ```
    pub fn beta_once(&mut self) {
        let mut done = false;
        self._beta_once(&mut done);
    }

    fn _beta_once(&mut self, done: &mut bool) {
        if *done { return }

        match *self {
            Var(_) => (),
            Abs(_) => self.unabs_ref_mut().unwrap()._beta_once(done),
            App(_, _) => {
                if self.lhs_ref().unwrap().unabs_ref().is_ok() {
                    let copy = self.clone();
                    if SHOW_REDUCTIONS { print!("    {} reduces to ", self) };
                    *self = copy.eval().unwrap();
                    if SHOW_REDUCTIONS { println!("{}", self) }
                    *done = true;
                } else {
                    self.lhs_ref_mut().unwrap()._beta_once(done);
                    self.rhs_ref_mut().unwrap()._beta_once(done)
                }
            }
        }
    }

    /// Performs full normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::pred;
    ///
    /// let mut pred_one = pred().app(1.into());
    /// pred_one.beta_full();
    ///
    /// assert_eq!(pred_one, 0.into());
    /// ```
    pub fn beta_full(&mut self) {
        let mut tmp;
        loop {
            if SHOW_REDUCTIONS { println!("reducing {}", self) }
            tmp = self.clone();
            self.beta_once();
            if *self == tmp { break }
        }

        if SHOW_REDUCTIONS { println!("    doesn't reduce") }
    }
}

/// Performs full normal-order β-reduction on a `Term`, consuming it in the process.
///
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::pred;
/// use lambda_calculus::reduction::beta_full;
///
/// let pred_one = pred().app(1.into());
///
/// assert_eq!(beta_full(pred_one), 0.into());
/// ```
pub fn beta_full(mut term: Term) -> Term {
    term.beta_full();
    term
}

/// Performs a single normal-order β-reduction on `self`.
///
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::succ;
/// use lambda_calculus::reduction::beta_once;
///
/// let succ_one = succ().app(1.into());
///
/// assert_eq!(beta_once(succ_one), succ().apply(&1.into()).unwrap());
/// ```
pub fn beta_once(mut term: Term) -> Term {
    term.beta_once();
    term
}

#[cfg(test)]
mod test {

}
<commit_msg>improve eval() doctest<commit_after>//! [β-reduction](https://en.wikipedia.org/wiki/Beta_normal_form) for lambda `Term`s

#![allow(dead_code)]

use term::*;
use term::Term::*;
/*
use self::Closure::*;
use self::Expression::*;
use std::collections::VecDeque;

#[derive(Debug, PartialEq, Clone)]
enum Closure {
    Depth(usize),
    TermInEnv(Term, Environment)
}

#[derive(Debug, PartialEq)]
enum Expression {
    Evaluation(Closure),
    Application(Box<Expression>, Term, Environment)
}

type Environment = VecDeque<Closure>;

fn whnf(term: Term, mut env: Environment) -> Expression {
    match term {
        Var(i) => match env.remove(i - 1) {
            Some(Depth(i)) => Evaluation(Depth(i)),
            Some(TermInEnv(t, e)) => whnf(t, e),
            None => unreachable!()
        },
        Abs(t) => Evaluation(TermInEnv(Abs(t), env)),
        App(lhs, rhs) => match whnf(*lhs, env.clone()) { // TODO: try to remove this clone()
            Evaluation(TermInEnv(Abs(lhs2), mut env2)) => {
                env2.push_front(TermInEnv(*rhs, env));
                whnf(*lhs2, env2)
            },
            expr => Application(Box::new(expr), *rhs, env)
        }
    }
}

fn reduce(depth: usize, exp: Expression) -> Term {
    match exp {
        Application(lhs, rhs, env) => app(reduce(depth, *lhs), nf(depth, rhs, env)),
        Evaluation(TermInEnv(Abs(term), mut env)) => {
            env.push_front(Depth(depth));
            abs(nf(depth + 1, *term, env))
        },
        Evaluation(TermInEnv(term, _)) => term,
        Evaluation(Depth(i)) => Var(depth - i)
    }
}

fn nf(depth: usize, term: Term, env: Environment) -> Term {
    reduce(depth, whnf(term, env))
}

/// Returns a term reduced to its normal form. Consumes its argument.
///
/// # Example
///
/// ```
/// use lambda_calculus::booleans::{if_else, tru};
/// use lambda_calculus::arithmetic::{zero, one, succ};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(succ().app(zero())), one());
/// assert_eq!(normalize(if_else().app(tru()).app(one()).app(zero())), one());
/// ```
fn normalize(term: Term) -> Term {
    nf(0, term, VecDeque::new())
}
*/
/// Applies two terms with substitution and variable update, consuming the first one in the process.
///
/// # Example
/// ```
/// use lambda_calculus::reduction::apply;
/// use lambda_calculus::parser::parse;
///
/// let lhs    = parse(&"λλ42(λ13)").unwrap();
/// let rhs    = parse(&"λ51").unwrap();
/// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
///
/// assert_eq!(apply(lhs, &rhs), Ok(result));
/// ```
pub fn apply(mut lhs: Term, rhs: &Term) -> Result<Term, Error> {
    _apply(&mut lhs, rhs, 0);

    lhs.unabs()
}

fn _apply(lhs: &mut Term, rhs: &Term, depth: usize) {
    match *lhs {
        Var(i) => if i == depth {
            *lhs = rhs.clone(); // substitute a top-level variable from lhs with rhs
            update_free_variables(lhs, depth - 1, 0); // update indices of free variables from rhs
        } else if i > depth {
            *lhs = Var(i - 1) // decrement a free variable's index
        },
        Abs(_) => {
            _apply(lhs.unabs_ref_mut().unwrap(), rhs, depth + 1)
        },
        App(_, _) => {
            _apply(lhs.lhs_ref_mut().unwrap(), rhs, depth);
            _apply(lhs.rhs_ref_mut().unwrap(), rhs, depth)
        }
    }
}

fn update_free_variables(term: &mut Term, added_depth: usize, own_depth: usize) {
    match *term {
        Var(i) => if i > own_depth {
            *term = Var(i + added_depth)
        },
        Abs(_) => {
            update_free_variables(term.unabs_ref_mut().unwrap(), added_depth, own_depth + 1)
        },
        App(_, _) => {
            update_free_variables(term.lhs_ref_mut().unwrap(), added_depth, own_depth);
            update_free_variables(term.rhs_ref_mut().unwrap(), added_depth, own_depth)
        }
    }
}

/// Set to `true` to see all the steps of β-reductions. The default is `false`.
pub const SHOW_REDUCTIONS: bool = false;

impl Term {
    /// Applies `self` to another term with substitution and variable update, consuming it
    /// in the process.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::parser::parse;
    ///
    /// let lhs    = parse(&"λλ42(λ13)").unwrap();
    /// let rhs    = parse(&"λ51").unwrap();
    /// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
    ///
    /// assert_eq!(lhs.apply(&rhs), Ok(result));
    /// ```
    pub fn apply(self, rhs: &Term) -> Result<Term, Error> {
        apply(self, rhs)
    }

    /// Reduces an `App`lication by substitution and variable update.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::{app, abs};
    /// use lambda_calculus::term::Term::Var;
    /// use lambda_calculus::arithmetic::zero;
    /// use lambda_calculus::combinators::i;
    ///
    /// assert_eq!(app(i(), zero()).eval(), Ok(zero()));
    /// ```
    pub fn eval(self) -> Result<Term, Error> {
        let (lhs, rhs) = try!(self.unapp());

        apply(lhs, &rhs)
    }

    /// Performs a single normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::succ;
    ///
    /// let mut succ_one = succ().app(1.into());
    /// succ_one.beta_once();
    ///
    /// assert_eq!(succ_one, succ().apply(&1.into()).unwrap());
    /// ```
    pub fn beta_once(&mut self) {
        let mut done = false;
        self._beta_once(&mut done);
    }

    fn _beta_once(&mut self, done: &mut bool) {
        if *done { return }

        match *self {
            Var(_) => (),
            Abs(_) => self.unabs_ref_mut().unwrap()._beta_once(done),
            App(_, _) => {
                if self.lhs_ref().unwrap().unabs_ref().is_ok() {
                    let copy = self.clone();
                    if SHOW_REDUCTIONS { print!("    {} reduces to ", self) };
                    *self = copy.eval().unwrap();
                    if SHOW_REDUCTIONS { println!("{}", self) }
                    *done = true;
                } else {
                    self.lhs_ref_mut().unwrap()._beta_once(done);
                    self.rhs_ref_mut().unwrap()._beta_once(done)
                }
            }
        }
    }

    /// Performs full normal-order β-reduction on `self`.
    ///
    /// # Example
    ///
    /// ```
    /// use lambda_calculus::arithmetic::pred;
    ///
    /// let mut pred_one = pred().app(1.into());
    /// pred_one.beta_full();
    ///
    /// assert_eq!(pred_one, 0.into());
    /// ```
    pub fn beta_full(&mut self) {
        let mut tmp;
        loop {
            if SHOW_REDUCTIONS { println!("reducing {}", self) }
            tmp = self.clone();
            self.beta_once();
            if *self == tmp { break }
        }

        if SHOW_REDUCTIONS { println!("    doesn't reduce") }
    }
}

/// Performs full normal-order β-reduction on a `Term`, consuming it in the process.
///
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::pred;
/// use lambda_calculus::reduction::beta_full;
///
/// let pred_one = pred().app(1.into());
///
/// assert_eq!(beta_full(pred_one), 0.into());
/// ```
pub fn beta_full(mut term: Term) -> Term {
    term.beta_full();
    term
}

/// Performs a single normal-order β-reduction on `self`.
///
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::succ;
/// use lambda_calculus::reduction::beta_once;
///
/// let succ_one = succ().app(1.into());
///
/// assert_eq!(beta_once(succ_one), succ().apply(&1.into()).unwrap());
/// ```
pub fn beta_once(mut term: Term) -> Term {
    term.beta_once();
    term
}

#[cfg(test)]
mod test {

}
<|endoftext|>


<commit_before>use std::str::FromStr;
use ::tokenize::tokenize_regex;
use ::expression::{Expression, Token, Multiplicity};

#[cfg(test)] mod spec;

#[derive(PartialEq,Debug)]
pub struct Regex {
    pub expressions: Vec<Expression>
}

impl Regex {
    pub fn from(pattern: &str) -> Result<Regex, &str> {
        tokenize_regex(pattern).map(|exprs| Regex {
            expressions: exprs
        })
    }

    pub fn first(&self, text: &str) -> Option<(usize, usize)> {
        let mut regex_i = 0; // the current position in the list of regex "expressions"
        let mut text_i = 0; // the current position in the text
        let mut match_start = 0; // the start position of the current match

        // a stack of valid offsets, in the order we encountered them
        let mut backtrack_stack = Vec::<(usize, usize, usize)>::new();

        while regex_i < self.expressions.len() {
            let mut options = self.expressions[regex_i].valid_offsets(&text[text_i..]);

            backtrack_stack.extend(options.iter()
                                     .map(|&option| (regex_i, text_i, option))
                                     .collect::<Vec<_>>());

            if backtrack_stack.len() == 0 {
                regex_i = 0;
                text_i += 1;
                match_start = text_i;

                if text_i >= text.len() {
                    return None;
                }

                continue;
            }

            let (reg_i,tex_i,chosen_option) = backtrack_stack.pop().unwrap();

            text_i = tex_i + chosen_option;
            regex_i = reg_i + 1;
        }

        Some((match_start, text_i))
    }

    pub fn is_match(&self, text: &str) -> bool {
        return self.first(text).is_some();
    }
}

<commit_msg>resolve warnings<commit_after>use ::tokenize::tokenize_regex;
use ::expression::{Expression};

#[cfg(test)] mod spec;

#[derive(PartialEq,Debug)]
pub struct Regex {
    pub expressions: Vec<Expression>
}

impl Regex {
    pub fn from(pattern: &str) -> Result<Regex, &str> {
        tokenize_regex(pattern).map(|exprs| Regex {
            expressions: exprs
        })
    }

    pub fn first(&self, text: &str) -> Option<(usize, usize)> {
        let mut regex_i = 0; // the current position in the list of regex "expressions"
        let mut text_i = 0; // the current position in the text
        let mut match_start = 0; // the start position of the current match

        // a stack of valid offsets, in the order we encountered them
        let mut backtrack_stack = Vec::<(usize, usize, usize)>::new();

        while regex_i < self.expressions.len() {
            let options = self.expressions[regex_i].valid_offsets(&text[text_i..]);

            backtrack_stack.extend(options.iter()
                                     .map(|&option| (regex_i, text_i, option))
                                     .collect::<Vec<_>>());

            if backtrack_stack.len() == 0 {
                regex_i = 0;
                text_i += 1;
                match_start = text_i;

                if text_i >= text.len() {
                    return None;
                }

                continue;
            }

            let (reg_i,tex_i,chosen_option) = backtrack_stack.pop().unwrap();

            text_i = tex_i + chosen_option;
            regex_i = reg_i + 1;
        }

        Some((match_start, text_i))
    }

    pub fn is_match(&self, text: &str) -> bool {
        return self.first(text).is_some();
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2015 Cesar Eduardo Barros
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the
// Software without restriction, including without
// limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use std::ops::BitXor;

#[derive(Clone, Copy, Debug)]
#[repr(C)]
#[simd]
pub struct vec4_u32(u32, u32, u32, u32);

#[derive(Clone, Copy, Debug)]
#[repr(C)]
#[simd]
struct u64x2(u64, u64);

#[derive(Clone, Copy, Debug)]
pub struct vec4_u64(u64x2, u64x2);

#[derive(Clone, Copy)] #[repr(C)] #[simd] struct i32x4(i32, i32, i32, i32);
#[derive(Clone, Copy)] #[repr(C)] #[simd] struct i64x2(i64, i64);

extern {
    #[link_name = "llvm.arm.neon.vshiftu.v4i32"]
    fn vshiftu_v4i32(a: vec4_u32, b: i32x4) -> vec4_u32;

    #[link_name = "llvm.arm.neon.vshiftu.v2i64"]
    fn vshiftu_v2i64(a: u64x2, b: i64x2) -> u64x2;
}

#[inline(always)]
fn vshlq_n_u32(a: vec4_u32, n: u32) -> vec4_u32 {
    let n_ = n as i32;
    unsafe { vshiftu_v4i32(a, i32x4(n_, n_, n_, n_)) }
}

#[inline(always)]
fn vshrq_n_u32(a: vec4_u32, n: u32) -> vec4_u32 {
    let n_ = -(n as i32);
    unsafe { vshiftu_v4i32(a, i32x4(n_, n_, n_, n_)) }
}

#[inline(always)]
fn vshlq_n_u64(a: u64x2, n: u32) -> u64x2 {
    let n_ = n as i64;
    unsafe { vshiftu_v2i64(a, i64x2(n_, n_)) }
}

#[inline(always)]
fn vshrq_n_u64(a: u64x2, n: u32) ->  u64x2 {
    let n_ = -(n as i64);
    unsafe { vshiftu_v2i64(a, i64x2(n_, n_)) }
}

#[cfg(feature = "simd_asm")]
#[inline(always)]
fn vrev32q_u16(a: vec4_u32) -> vec4_u32 {
    unsafe {
        let result: vec4_u32;
        asm!("vrev32.16 $0, $1"
           : "=w" (result)
           : "w" (a));
        result
    }
}

#[cfg(feature = "simd_asm")]
#[inline(always)]
fn vrev64q_u32(a: u64x2) -> u64x2 {
    unsafe {
        let result: u64x2;
        asm!("vrev64.32 $0, $1"
           : "=w" (result)
           : "w" (a));
        result
    }
}

impl vec4_u32 {
    #[inline(always)]
    pub fn new(a: u32, b: u32, c: u32, d: u32) -> Self {
        vec4_u32(a, b, c, d)
    }

    #[inline(always)] pub fn from_le(self) -> Self { self }
    #[inline(always)] pub fn to_le(self) -> Self { self }

    #[inline(always)]
    pub fn wrapping_add(self, rhs: Self) -> Self {
        self + rhs
    }

    #[inline(always)]
    fn rotate_right_any(self, n: u32) -> Self {
        vshrq_n_u32(self, n) ^ vshlq_n_u32(self, 32 - n)
    }

    #[cfg(feature = "simd_asm")]
    #[inline(always)]
    pub fn rotate_right(self, n: u32) -> Self {
        match n {
            16 => vrev32q_u16(self),
            _ => self.rotate_right_any(n),
        }
    }

    #[cfg(not(feature = "simd_asm"))]
    #[inline(always)]
    pub fn rotate_right(self, n: u32) -> Self {
        self.rotate_right_any(n)
    }

    #[inline(always)]
    pub fn shuffle_left_1(self) -> Self {
        vec4_u32(self.1, self.2, self.3, self.0)
    }

    #[inline(always)]
    pub fn shuffle_left_2(self) -> Self {
        vec4_u32(self.2, self.3, self.0, self.1)
    }

    #[inline(always)]
    pub fn shuffle_left_3(self) -> Self {
        vec4_u32(self.3, self.0, self.1, self.2)
    }

    #[inline(always)]
    pub fn shuffle_right_1(self) -> Self { self.shuffle_left_3() }

    #[inline(always)]
    pub fn shuffle_right_2(self) -> Self { self.shuffle_left_2() }

    #[inline(always)]
    pub fn shuffle_right_3(self) -> Self { self.shuffle_left_1() }
}

impl BitXor for vec4_u64 {
    type Output = Self;

    #[inline(always)]
    fn bitxor(self, rhs: Self) -> Self::Output {
        vec4_u64(self.0 ^ rhs.0,
                 self.1 ^ rhs.1)
    }
}

impl vec4_u64 {
    #[inline(always)]
    pub fn new(a: u64, b: u64, c: u64, d: u64) -> Self {
        vec4_u64(u64x2(a, b), u64x2(c, d))
    }

    #[inline(always)] pub fn from_le(self) -> Self { self }
    #[inline(always)] pub fn to_le(self) -> Self { self }

    #[inline(always)]
    pub fn wrapping_add(self, rhs: Self) -> Self {
        vec4_u64(self.0 + rhs.0, self.1 + rhs.1)
    }

    #[inline(always)]
    fn rotate_right_any(self, n: u32) -> Self {
        vec4_u64(vshrq_n_u64(self.0, n) ^ vshlq_n_u64(self.0, 64 - n),
                 vshrq_n_u64(self.1, n) ^ vshlq_n_u64(self.1, 64 - n))
    }

    #[cfg(feature = "simd_asm")]
    #[inline(always)]
    pub fn rotate_right(self, n: u32) -> Self {
        match n {
            32 => vec4_u64(vrev64q_u32(self.0), vrev64q_u32(self.1)),
            _ => self.rotate_right_any(n),
        }
    }

    #[cfg(not(feature = "simd_asm"))]
    #[inline(always)]
    pub fn rotate_right(self, n: u32) -> Self {
        self.rotate_right_any(n)
    }

    #[inline(always)]
    pub fn shuffle_left_1(self) -> Self {
        vec4_u64(u64x2((self.0).1, (self.1).0), u64x2((self.1).1, (self.0).0))
    }

    #[inline(always)]
    pub fn shuffle_left_2(self) -> Self {
        vec4_u64(self.1, self.0)
    }

    #[inline(always)]
    pub fn shuffle_left_3(self) -> Self {
        vec4_u64(u64x2((self.1).1, (self.0).0), u64x2((self.0).1, (self.1).0))
    }

    #[inline(always)]
    pub fn shuffle_right_1(self) -> Self { self.shuffle_left_3() }

    #[inline(always)]
    pub fn shuffle_right_2(self) -> Self { self.shuffle_left_2() }

    #[inline(always)]
    pub fn shuffle_right_3(self) -> Self { self.shuffle_left_1() }
}
<commit_msg>Use VEXT for NEON<commit_after>// Copyright (c) 2015 Cesar Eduardo Barros
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the
// Software without restriction, including without
// limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use std::ops::BitXor;

#[derive(Clone, Copy, Debug)]
#[repr(C)]
#[simd]
pub struct vec4_u32(u32, u32, u32, u32);

#[derive(Clone, Copy, Debug)]
#[repr(C)]
#[simd]
struct u64x2(u64, u64);

#[derive(Clone, Copy, Debug)]
pub struct vec4_u64(u64x2, u64x2);

#[derive(Clone, Copy)] #[repr(C)] #[simd] struct i32x4(i32, i32, i32, i32);
#[derive(Clone, Copy)] #[repr(C)] #[simd] struct i64x2(i64, i64);

extern {
    #[link_name = "llvm.arm.neon.vshiftu.v4i32"]
    fn vshiftu_v4i32(a: vec4_u32, b: i32x4) -> vec4_u32;

    #[link_name = "llvm.arm.neon.vshiftu.v2i64"]
    fn vshiftu_v2i64(a: u64x2, b: i64x2) -> u64x2;
}

#[inline(always)]
fn vshlq_n_u32(a: vec4_u32, n: u32) -> vec4_u32 {
    let n_ = n as i32;
    unsafe { vshiftu_v4i32(a, i32x4(n_, n_, n_, n_)) }
}

#[inline(always)]
fn vshrq_n_u32(a: vec4_u32, n: u32) -> vec4_u32 {
    let n_ = -(n as i32);
    unsafe { vshiftu_v4i32(a, i32x4(n_, n_, n_, n_)) }
}

#[inline(always)]
fn vshlq_n_u64(a: u64x2, n: u32) -> u64x2 {
    let n_ = n as i64;
    unsafe { vshiftu_v2i64(a, i64x2(n_, n_)) }
}

#[inline(always)]
fn vshrq_n_u64(a: u64x2, n: u32) ->  u64x2 {
    let n_ = -(n as i64);
    unsafe { vshiftu_v2i64(a, i64x2(n_, n_)) }
}

#[cfg(feature = "simd_asm")]
#[inline(always)]
fn vrev32q_u16(a: vec4_u32) -> vec4_u32 {
    unsafe {
        let result: vec4_u32;
        asm!("vrev32.16 $0, $1"
           : "=w" (result)
           : "w" (a));
        result
    }
}

#[cfg(feature = "simd_asm")]
#[inline(always)]
fn vrev64q_u32(a: u64x2) -> u64x2 {
    unsafe {
        let result: u64x2;
        asm!("vrev64.32 $0, $1"
           : "=w" (result)
           : "w" (a));
        result
    }
}

#[cfg(feature = "simd_asm")]
#[inline(always)]
fn vext_u64_u8(a: u64x2, b: u8) -> u64x2 {
    unsafe {
        let result: u64x2;
        asm!("vext.8 ${0:e}, ${1:e}, ${1:e}, $2\nvext.8 ${0:f}, ${1:f}, ${1:f}, $2"
           : "=w" (result)
           : "w" (a), "n" (b));
        result
    }
}

impl vec4_u32 {
    #[inline(always)]
    pub fn new(a: u32, b: u32, c: u32, d: u32) -> Self {
        vec4_u32(a, b, c, d)
    }

    #[inline(always)] pub fn from_le(self) -> Self { self }
    #[inline(always)] pub fn to_le(self) -> Self { self }

    #[inline(always)]
    pub fn wrapping_add(self, rhs: Self) -> Self {
        self + rhs
    }

    #[inline(always)]
    fn rotate_right_any(self, n: u32) -> Self {
        vshrq_n_u32(self, n) ^ vshlq_n_u32(self, 32 - n)
    }

    #[cfg(feature = "simd_asm")]
    #[inline(always)]
    pub fn rotate_right(self, n: u32) -> Self {
        match n {
            16 => vrev32q_u16(self),
            _ => self.rotate_right_any(n),
        }
    }

    #[cfg(not(feature = "simd_asm"))]
    #[inline(always)]
    pub fn rotate_right(self, n: u32) -> Self {
        self.rotate_right_any(n)
    }

    #[inline(always)]
    pub fn shuffle_left_1(self) -> Self {
        vec4_u32(self.1, self.2, self.3, self.0)
    }

    #[inline(always)]
    pub fn shuffle_left_2(self) -> Self {
        vec4_u32(self.2, self.3, self.0, self.1)
    }

    #[inline(always)]
    pub fn shuffle_left_3(self) -> Self {
        vec4_u32(self.3, self.0, self.1, self.2)
    }

    #[inline(always)]
    pub fn shuffle_right_1(self) -> Self { self.shuffle_left_3() }

    #[inline(always)]
    pub fn shuffle_right_2(self) -> Self { self.shuffle_left_2() }

    #[inline(always)]
    pub fn shuffle_right_3(self) -> Self { self.shuffle_left_1() }
}

impl BitXor for vec4_u64 {
    type Output = Self;

    #[inline(always)]
    fn bitxor(self, rhs: Self) -> Self::Output {
        vec4_u64(self.0 ^ rhs.0,
                 self.1 ^ rhs.1)
    }
}

impl vec4_u64 {
    #[inline(always)]
    pub fn new(a: u64, b: u64, c: u64, d: u64) -> Self {
        vec4_u64(u64x2(a, b), u64x2(c, d))
    }

    #[inline(always)] pub fn from_le(self) -> Self { self }
    #[inline(always)] pub fn to_le(self) -> Self { self }

    #[inline(always)]
    pub fn wrapping_add(self, rhs: Self) -> Self {
        vec4_u64(self.0 + rhs.0, self.1 + rhs.1)
    }

    #[inline(always)]
    fn rotate_right_any(self, n: u32) -> Self {
        vec4_u64(vshrq_n_u64(self.0, n) ^ vshlq_n_u64(self.0, 64 - n),
                 vshrq_n_u64(self.1, n) ^ vshlq_n_u64(self.1, 64 - n))
    }

    #[cfg(feature = "simd_asm")]
    #[inline(always)]
    pub fn rotate_right(self, n: u32) -> Self {
        match n {
            32 => vec4_u64(vrev64q_u32(self.0), vrev64q_u32(self.1)),
            24 => vec4_u64(vext_u64_u8(self.0, 3), vext_u64_u8(self.1, 3)),
            16 => vec4_u64(vext_u64_u8(self.0, 2), vext_u64_u8(self.1, 2)),
            _ => self.rotate_right_any(n),
        }
    }

    #[cfg(not(feature = "simd_asm"))]
    #[inline(always)]
    pub fn rotate_right(self, n: u32) -> Self {
        self.rotate_right_any(n)
    }

    #[inline(always)]
    pub fn shuffle_left_1(self) -> Self {
        vec4_u64(u64x2((self.0).1, (self.1).0), u64x2((self.1).1, (self.0).0))
    }

    #[inline(always)]
    pub fn shuffle_left_2(self) -> Self {
        vec4_u64(self.1, self.0)
    }

    #[inline(always)]
    pub fn shuffle_left_3(self) -> Self {
        vec4_u64(u64x2((self.1).1, (self.0).0), u64x2((self.0).1, (self.1).0))
    }

    #[inline(always)]
    pub fn shuffle_right_1(self) -> Self { self.shuffle_left_3() }

    #[inline(always)]
    pub fn shuffle_right_2(self) -> Self { self.shuffle_left_2() }

    #[inline(always)]
    pub fn shuffle_right_3(self) -> Self { self.shuffle_left_1() }
}
<|endoftext|>


<commit_before>use super::super::RW;
use super::super::thread::{Handler, Message};
use super::super::evented::{EventSourceTrait, RcEventSource, Evented, EventedImpl};
use super::super::mio_orig::{EventLoop, Token, EventSet};
use std::sync::Arc;
use spin::Mutex;
use super::super::thread::MioSender;
use super::super::{sender_retry, in_coroutine};

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc;
type ArcChannelShared = Arc<Mutex<ChannelShared>>;
type ArcCounter = Arc<AtomicUsize>;

/// State shared between senders and receiver.
struct ChannelShared {
    token: Option<Token>,
    sender: Option<MioSender>,
}

/// Channel receiving end
///
/// Create with `channel()`
pub struct Receiver<T>(RcEventSource<ReceiverCore<T>>);

struct ReceiverCore<T> {
    receiver : mpsc::Receiver<T>,
    shared : ArcChannelShared,
    counter : ArcCounter,
}

impl<T> EventedImpl for Receiver<T> where T: 'static
{
    type Raw = ReceiverCore<T>;

    fn shared(&self) -> &RcEventSource<ReceiverCore<T>> {
        &self.0
    }
}

impl<T> EventSourceTrait for ReceiverCore<T> {
    fn register(&self, event_loop: &mut EventLoop<Handler>, token: Token, interest: EventSet) {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): register", token.as_usize());
        let mut lock = self.shared.lock();

        lock.token = Some(token);
        lock.sender = Some(event_loop.channel());

        if self.counter.load(Ordering::SeqCst) != 0 {
            trace!("Receiver({}): not empty; self notify",
                   token.as_usize());
            lock.token = None;
            let sender = lock.sender.clone().unwrap();
            // don't loop holding a lock
            drop(lock);
            sender_retry(&sender, Message::ChannelMsg(token));
        }
    }

    fn reregister(&self, _event_loop: &mut EventLoop<Handler>, token: Token, interest: EventSet) {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): reregister", token.as_usize());
        let mut lock = self.shared.lock();

        debug_assert!(lock.token.is_some());
        debug_assert!(lock.sender.is_some());

        if self.counter.load(Ordering::SeqCst) != 0 {
            lock.token = None;
            let sender = lock.sender.clone().unwrap();
            // don't loop holding a lock
            drop(lock);
            sender_retry(&sender, Message::ChannelMsg(token));
        }
    }

    fn deregister(&self, _event_loop: &mut EventLoop<Handler>, token: Token) {
        trace!("Receiver({}): dereregister", token.as_usize());
        let mut lock = self.shared.lock();
        lock.token = None;
        lock.sender = None;
    }
}

impl<T> Receiver<T> {
    fn new(shared: ArcChannelShared, counter : ArcCounter, receiver : mpsc::Receiver<T>) -> Self {
        let core = ReceiverCore {
            shared: shared,
            counter: counter,
            receiver: receiver,
        };

        Receiver(RcEventSource::new(core))
    }
}

impl<T> Receiver<T> where T: 'static
{
    /// Receive `T` sent using corresponding `Sender::send()`.
    ///
    /// Will block coroutine if no elements are available.
    pub fn recv(&self) -> Result<T, mpsc::RecvError> {
        if in_coroutine() {
            loop {
                let recv = self.try_recv();

                match recv {
                    Err(mpsc::TryRecvError::Empty) => self.block_on(RW::read()),
                    Err(mpsc::TryRecvError::Disconnected) => return Err(mpsc::RecvError),
                    Ok(t) => {
                        return Ok(t)
                    },
                }
                debug_assert!(self.empty_shared_token());
            }
        } else {
            self.shared().io_ref().receiver.recv()
        }
    }

    /// Try reading data from the queue.
    ///
    /// This will not block.
    pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let res = io_ref.receiver.try_recv();
        if res.is_ok() {
            let prev_counter = self.shared().io_ref().counter.fetch_sub(1, Ordering::SeqCst);
            debug_assert!(prev_counter > 0);
        }
        res
    }

    fn empty_shared_token(&self) -> bool {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let lock = io_ref.shared.lock();
        lock.token.is_none()
    }
}

/// Channel sending end
///
/// Use this inside mioco coroutines or outside of mioco itself to send data
/// asynchronously to the receiving end.
///
/// Create with `channel()`
pub struct Sender<T> {
    sender : mpsc::Sender<T>,
    shared : ArcChannelShared,
    counter : ArcCounter,
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Self {
        Sender {
            shared: self.shared.clone(),
            sender: self.sender.clone(),
            counter: self.counter.clone(),
        }
    }
}

impl<T> Sender<T> {
    fn new(shared: ArcChannelShared, counter : ArcCounter, sender: mpsc::Sender<T>) -> Self {
        Sender{
            shared: shared,
            counter: counter,
            sender: sender,
        }
    }
}

impl<T> Sender<T> {
    /// Deliver `T` to the other end of the channel.
    ///
    /// Channel behaves like a queue.
    ///
    /// This is non-blocking operation.
    pub fn send(&self, t: T) -> Result<(), mpsc::SendError<T>> {
        try!(self.sender.send(t));
        let prev_counter = self.counter.fetch_add(1, Ordering::SeqCst);

        if prev_counter == 0 {
            self.maybe_notify_receiver();
        }
        Ok(())
    }

    fn maybe_notify_receiver(&self) {
        let mut lock = self.shared.lock();
        let ChannelShared {
            ref mut sender,
            ref mut token,
        } = *lock;

        if let Some(token) = *token {
            trace!("Sender: notifying {:?}", token);
            let sender = sender.as_ref().unwrap();
            sender_retry(&sender, Message::ChannelMsg(token))
        }
    }
}

/// Create a channel
///
/// Channel can be used to deliver data via MPSC queue.
///
/// Channel is modeled after `std::sync::mpsc::channel()`, only
/// supporting mioco-aware sending and receiving.
///
/// When receiving end is outside of coroutine, channel will behave just
/// like `std::sync::mpsc::channel()`.
pub fn channel <T>() -> (Sender<T>, Receiver<T>) {
    let shared = ChannelShared {
        token: None,
        sender: None,
    };

    let shared = Arc::new(Mutex::new(shared));

    let counter = Arc::new(AtomicUsize::new(0));
    let (sender, receiver) = mpsc::channel();
    (
        Sender::new(shared.clone(), counter.clone(), sender),
        Receiver::new(shared, counter, receiver),
        )
}

unsafe impl<T> Send for Receiver<T> {}
<commit_msg>mpsc: Remove wrong assert.<commit_after>use super::super::RW;
use super::super::thread::{Handler, Message};
use super::super::evented::{EventSourceTrait, RcEventSource, Evented, EventedImpl};
use super::super::mio_orig::{EventLoop, Token, EventSet};
use std::sync::Arc;
use spin::Mutex;
use super::super::thread::MioSender;
use super::super::{sender_retry, in_coroutine};

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc;
type ArcChannelShared = Arc<Mutex<ChannelShared>>;
type ArcCounter = Arc<AtomicUsize>;

/// State shared between senders and receiver.
struct ChannelShared {
    token: Option<Token>,
    sender: Option<MioSender>,
}

/// Channel receiving end
///
/// Create with `channel()`
pub struct Receiver<T>(RcEventSource<ReceiverCore<T>>);

struct ReceiverCore<T> {
    receiver : mpsc::Receiver<T>,
    shared : ArcChannelShared,
    counter : ArcCounter,
}

impl<T> EventedImpl for Receiver<T> where T: 'static
{
    type Raw = ReceiverCore<T>;

    fn shared(&self) -> &RcEventSource<ReceiverCore<T>> {
        &self.0
    }
}

impl<T> EventSourceTrait for ReceiverCore<T> {
    fn register(&self, event_loop: &mut EventLoop<Handler>, token: Token, interest: EventSet) {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): register", token.as_usize());
        let mut lock = self.shared.lock();

        lock.token = Some(token);
        lock.sender = Some(event_loop.channel());

        if self.counter.load(Ordering::SeqCst) != 0 {
            trace!("Receiver({}): not empty; self notify",
                   token.as_usize());
            lock.token = None;
            let sender = lock.sender.clone().unwrap();
            // don't loop holding a lock
            drop(lock);
            sender_retry(&sender, Message::ChannelMsg(token));
        }
    }

    fn reregister(&self, _event_loop: &mut EventLoop<Handler>, token: Token, interest: EventSet) {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): reregister", token.as_usize());
        let mut lock = self.shared.lock();

        debug_assert!(lock.token.is_some());
        debug_assert!(lock.sender.is_some());

        if self.counter.load(Ordering::SeqCst) != 0 {
            lock.token = None;
            let sender = lock.sender.clone().unwrap();
            // don't loop holding a lock
            drop(lock);
            sender_retry(&sender, Message::ChannelMsg(token));
        }
    }

    fn deregister(&self, _event_loop: &mut EventLoop<Handler>, token: Token) {
        trace!("Receiver({}): dereregister", token.as_usize());
        let mut lock = self.shared.lock();
        lock.token = None;
        lock.sender = None;
    }
}

impl<T> Receiver<T> {
    fn new(shared: ArcChannelShared, counter : ArcCounter, receiver : mpsc::Receiver<T>) -> Self {
        let core = ReceiverCore {
            shared: shared,
            counter: counter,
            receiver: receiver,
        };

        Receiver(RcEventSource::new(core))
    }
}

impl<T> Receiver<T> where T: 'static
{
    /// Receive `T` sent using corresponding `Sender::send()`.
    ///
    /// Will block coroutine if no elements are available.
    pub fn recv(&self) -> Result<T, mpsc::RecvError> {
        if in_coroutine() {
            loop {
                let recv = self.try_recv();

                match recv {
                    Err(mpsc::TryRecvError::Empty) => self.block_on(RW::read()),
                    Err(mpsc::TryRecvError::Disconnected) => return Err(mpsc::RecvError),
                    Ok(t) => {
                        return Ok(t)
                    },
                }
                debug_assert!(self.empty_shared_token());
            }
        } else {
            self.shared().io_ref().receiver.recv()
        }
    }

    /// Try reading data from the queue.
    ///
    /// This will not block.
    pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let res = io_ref.receiver.try_recv();
        if res.is_ok() {
            let _prev_counter = self.shared().io_ref().counter.fetch_sub(1, Ordering::SeqCst);
            // since send() first sends, then increases the counter, it is
            // possible for _prev_counter to be zero
        }
        res
    }

    fn empty_shared_token(&self) -> bool {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let lock = io_ref.shared.lock();
        lock.token.is_none()
    }
}

/// Channel sending end
///
/// Use this inside mioco coroutines or outside of mioco itself to send data
/// asynchronously to the receiving end.
///
/// Create with `channel()`
pub struct Sender<T> {
    sender : mpsc::Sender<T>,
    shared : ArcChannelShared,
    counter : ArcCounter,
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Self {
        Sender {
            shared: self.shared.clone(),
            sender: self.sender.clone(),
            counter: self.counter.clone(),
        }
    }
}

impl<T> Sender<T> {
    fn new(shared: ArcChannelShared, counter : ArcCounter, sender: mpsc::Sender<T>) -> Self {
        Sender{
            shared: shared,
            counter: counter,
            sender: sender,
        }
    }
}

impl<T> Sender<T> {
    /// Deliver `T` to the other end of the channel.
    ///
    /// Channel behaves like a queue.
    ///
    /// This is non-blocking operation.
    pub fn send(&self, t: T) -> Result<(), mpsc::SendError<T>> {
        try!(self.sender.send(t));
        let prev_counter = self.counter.fetch_add(1, Ordering::SeqCst);

        if prev_counter == 0 {
            self.maybe_notify_receiver();
        }
        Ok(())
    }

    fn maybe_notify_receiver(&self) {
        let mut lock = self.shared.lock();
        let ChannelShared {
            ref mut sender,
            ref mut token,
        } = *lock;

        if let Some(token) = *token {
            trace!("Sender: notifying {:?}", token);
            let sender = sender.as_ref().unwrap();
            sender_retry(&sender, Message::ChannelMsg(token))
        }
    }
}

/// Create a channel
///
/// Channel can be used to deliver data via MPSC queue.
///
/// Channel is modeled after `std::sync::mpsc::channel()`, only
/// supporting mioco-aware sending and receiving.
///
/// When receiving end is outside of coroutine, channel will behave just
/// like `std::sync::mpsc::channel()`.
pub fn channel <T>() -> (Sender<T>, Receiver<T>) {
    let shared = ChannelShared {
        token: None,
        sender: None,
    };

    let shared = Arc::new(Mutex::new(shared));

    let counter = Arc::new(AtomicUsize::new(0));
    let (sender, receiver) = mpsc::channel();
    (
        Sender::new(shared.clone(), counter.clone(), sender),
        Receiver::new(shared, counter, receiver),
        )
}

unsafe impl<T> Send for Receiver<T> {}
<|endoftext|>


<commit_before>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! Provide basic definitions of terms.

use std::collections::BitVec;
//use std::tuple::Tuple1;

/// Represents root terms.
struct Root ( () );
struct Any ( () );
struct ENone ( () );
#[derive(Debug)]
struct EString( String ) ;
impl EString{
    fn new(val: &str) -> Self { EString(val.to_string()) }
}

struct Symbol( String );
#[derive(Debug)]
struct Integer( isize );
impl Integer{
    fn new(val: isize) -> Self { Integer(val) }
}

struct Float( f64 );
struct BitString( BitVec );
struct Boolean( bool );
//#[derive(Debug)]
//struct Term<T> ( T );

trait RootType<T>{
    fn native(&self) -> &T;
}
impl RootType<String> for EString{
    fn native(&self) -> &String { &self.0 }
}
impl RootType<isize> for Integer{
    fn native(&self) -> &isize { &self.0 }
}

trait Term{
    fn to_string(&self) -> String { "This is a Term.".to_string() }
}

impl Term for EString{
    fn to_string(&self) -> String { "This is an EString".to_string() }
}

impl Term for Integer{
    fn to_string(&self) -> String {"This is an Integer".to_string() }
}

#[test]
fn term_type_check_test() -> (){
    let mut estring = EString("Test".to_string());
    let integer = Integer(3);
    // Uncomment the following line to see the term type checker assist in action
    // stringterm = integerterm;
    // The following line shoudl fail to compile because i32 does not have the Termable trait.
    //estring = integer;

    panic!("Intentionial panic. {:?}", estring.to_string());
}

<commit_msg>Added a rudimentary Lambda to have a non-trivial root type.<commit_after>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! Provide basic definitions of terms.

use std::collections::BitVec;
use std::rc::Rc;

/// Represents root terms.
struct Root ( () );
struct Any ( () );
struct ENone ( () );

#[derive(Debug)]
struct EString( String ) ;
impl EString{
    fn new(val: &str) -> Self { EString(val.to_string()) }
}

struct Symbol( String );
#[derive(Debug)]
struct Integer( isize );
impl Integer{
    fn new(val: isize) -> Self { Integer(val) }
}

struct Float( f64 );
struct BitString( BitVec );
struct Boolean( bool );

//For simplicity while experimenting, I'm not using Rc<T>
//Can't derive Debug automatically for Term
//#[derive(Debug)]
struct Lambda{
    parameter: Box<Term>,
    guard    : Box<Term>,
    body     : Box<Term>,
    //type,
    index    : usize,
    stuff     : (),
}
impl Lambda{
    fn new(p: Box<Term>, g: Box<Term>, b: Box<Term>) -> Self{
        Lambda{parameter: p, guard: g, body: b, index: 0, stuff: ()}
    }
}

trait RootType<T>{
    fn native(&self) -> &T;
}
impl RootType<String> for EString{
    fn native(&self) -> &String { &self.0 }
}
impl RootType<isize> for Integer{
    fn native(&self) -> &isize { &self.0 }
}

trait Term{
    fn to_string(&self) -> String { "This is a Term.".to_string() }
}

impl Term for EString{
    fn to_string(&self) -> String { "This is an EString".to_string() }
}

impl Term for Integer{
    fn to_string(&self) -> String {"This is an Integer".to_string() }
}

impl Term for Lambda{
    fn to_string(&self) -> String {"This is a Lambda.".to_string() }
}

#[test]
fn term_type_check_test() -> (){
    let estring = EString("Test".to_string());
    let integer = Integer::new(3);
    let i2 = Integer::new(5);
    let lambda = Lambda::new(Box::new(estring), Box::new(integer),
                 Box::new(i2));
    // Uncomment the following line to see the term type checker assist in action
    // stringterm = integerterm;
    // The following line shoudl fail to compile because i32 does not have the Termable trait.
    //estring = integer;

    panic!("Intentionial panic. {:?}", lambda.to_string() );
}

<|endoftext|>