<commit_before>use datum::*;
use primitive::*;
use numeric::LNumeric;
use core::num::Zero::zero;
use core::num::One::one;
use core::hashmap::linear::LinearMap;
use stack::*;

struct Runtime {
    stdin: @io::Reader,
    stdout: @io::Writer,
    stderr: @io::Writer,
    env: @mut Stack<LinearMap<@str, @LDatum>>,
    syntax: LinearMap<@str, PrimSyntax>,
    qq_lvl: uint,
}

#[deriving(Eq)]
enum RuntimeError {
    UnboundVariable(@str),
    NotCallable,
    NotList,
    ArgNumError(uint, bool, uint),
    TypeError,
    DivideByZeroError,
    NilEval,
    BadSyntax(PrimSyntax, ~str),
}

impl ToStr for RuntimeError {
    fn to_str(&self) -> ~str {
        err_to_str(self)
    }
}

priv fn err_to_str(&err: &RuntimeError) -> ~str {
    match err {
        UnboundVariable(name) => ~"unbound variable: " + name,
        NotCallable => ~"not callable",
        NotList => ~"not list",
        ArgNumError(expected, false, argnum) => {
            fmt!("expected %u arguments, but found %u arguments", expected, argnum)
        },
        ArgNumError(expected, true, argnum) => {
            fmt!("expected %u or more arguments, but found %u arguments", expected, argnum)
        },
        TypeError => ~"type error",
        DivideByZeroError => ~"divide by zero",
        NilEval => ~"() cannot be evaluated",
        BadSyntax(syn, reason) => ~"bad syntax for " + syn.to_str() + ": " + reason,
    }
}

fn load_prelude() -> LinearMap<@str, @LDatum> {
    let mut map = LinearMap::new();
    for vec::each(prelude()) |&pair| {
        let (key, func) = pair;
        map.insert(key, @LPrim(func));
    }
    map
}

fn load_prelude_macro() -> LinearMap<@str, PrimSyntax> {
    let mut map = LinearMap::new();
    for vec::each(syntax_prelude()) |&pair| {
        let (key, syntax) = pair;
        map.insert(key, syntax);
    }
    map
}

priv fn call_prim1(args: ~[@LDatum],
                op: &fn(@LDatum) -> Result<@LDatum, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    if args.len() == 1 {
        op(args[0])
    } else {
        Err(ArgNumError(1, false, args.len()))
    }
}

priv fn call_prim2(args: ~[@LDatum],
                op: &fn(@LDatum, @LDatum) -> Result<@LDatum, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    if args.len() == 2 {
        op(args[0], args[1])
    } else {
        Err(ArgNumError(2, false, args.len()))
    }
}

priv fn call_num_prim2(args: ~[@LDatum],
                    op: &fn(&LNumeric, &LNumeric) -> Result<@LDatum, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    if args.len() == 2 {
        match *args[0] {
            LNum(lhs) => match *args[1] {
                LNum(rhs) => op(&lhs, &rhs),
                _ => Err(TypeError),
            },
            _ => Err(TypeError),
        }
    } else {
        Err(ArgNumError(2, false, args.len()))
    }
}

priv fn call_num_foldl(args: ~[@LDatum],
                    a0: LNumeric,
                    op: &fn(&LNumeric, &LNumeric) -> Result<LNumeric, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    let mut res = a0;
    let mut err = false;
    do args.each |&arg| {
        match *arg {
            LNum(a) => {
                match op(&res, &a) {
                    Ok(n) => {
                        res = n;
                        err = false;
                    },
                    _ => {
                        err = true;
                    }
                }
            },
            _ => {
                err = true;
            }
        }
        !err
    }
    if err {
        Err(TypeError)
    } else {
        Ok(@LNum(res))
    }
}

priv fn get_syms(&arg: &@LDatum) -> Result<(~[@str], Option<@str>), ~str> {
    let mut iter = arg;
    let mut args : ~[@str] = ~[];
    let mut varargs : Option<@str> = None;

    loop {
        match *iter {
            LCons(h, t) => match *h {
                LIdent(name) => {
                    args.push(name);
                    iter = t;
                },
                _ => {
                    return Err(~"non-symbol argument");
                }
            },
            LIdent(name) => {
                varargs = Some(name);
                break;
            },
            LNil => {
                break;
            },
            _ => {
                return Err(~"non-list argument");
            },
        }
    }

    Ok((args, varargs))
}

priv impl Runtime {
    fn get_syntax(&self, val: @LDatum) -> Option<PrimSyntax> {
        match *val {
            LIdent(name) => match self.syntax.find(&name) {
                Some(&syn) => Some(syn),
                None => None,
            },
            _ => None,
        }
    }

    fn run_syntax(&mut self,
                syn: PrimSyntax,
                args: ~[@LDatum]) -> Result<@LDatum, RuntimeError>
    {
        match syn {
            SynIf => if args.len() == 3 {
                    do result::chain(self.eval(args[0])) |cond| {
                        match *cond {
                            LBool(true) => self.eval(args[1]),
                            LBool(false) => self.eval(args[2]),
                            _ => Err(TypeError),
                        }
                    }
                } else {
                    Err(BadSyntax(SynIf, ~"bad number of arguments"))
                },
            SynLambda => if args.len() < 2 {
                    Err(BadSyntax(SynLambda, ~"no body given"))
                } else {
                    match get_syms(&args[0]) {
                        Err(e) => Err(BadSyntax(SynLambda, e)),
                        Ok((anames, varargs)) => {
                            let seq = vec::from_slice(vec::slice(args, 1, args.len()));
                            Ok(@LProc(anames, varargs, seq, self.env))
                        },
                    }
                },
            SynDefine => if args.len() < 2 {
                    Err(BadSyntax(SynDefine, ~"no body given"))
                } else {
                    match get_syms(&args[0]) {
                        Err(e) => Err(BadSyntax(SynDefine, e)),
                        Ok((anames, varargs)) =>
                            if anames.is_empty() {
                                match varargs {
                                    None => Err(BadSyntax(SynDefine, ~"name not given")),
                                    Some(name) => if args.len() != 2 {
                                            Err(BadSyntax(SynDefine, ~"multiple expressions"))
                                        } else {
                                            do result::map(&self.eval(args[1])) |&val| {
                                                let mut frame = LinearMap::new();
                                                frame.insert(name, val);
                                                self.env = @mut push(self.env, frame);
                                                @LNil
                                            }
                                        }
                                }
                            } else {
                                let name = anames[0];
                                let anames = vec::from_slice(vec::slice(anames, 1, anames.len()));
                                let seq = vec::from_slice(vec::slice(args, 1, args.len()));
                                let proc = @LProc(anames, varargs, seq, self.env);
                                let mut frame = LinearMap::new();
                                frame.insert(name, proc);
                                self.env = @mut push(self.env, frame);
                                Ok(@LNil)
                            }
                    }
                },
            SynSet => if args.len() != 2 {
                    Err(BadSyntax(SynSet, ~"bad number of arguments"))
                } else {
                    match *args[0] {
                        LIdent(name) => do result::chain(self.eval(args[1])) |val| {
                            if set_var(self.env, &name, val) {
                                Ok(@LNil)
                            } else {
                                Err(BadSyntax(SynSet, ~"unbound variable"))
                            }
                        },
                        _ => Err(BadSyntax(SynSet, ~"cannot set non-variable"))
                    }
                },
            SynQuote => if args.len() == 1 {
                    Ok(args[0])
                } else {
                    Err(BadSyntax(SynQuote, ~"bad number of arguments"))
                },
            SynQQuote => if args.len() == 1 {
                    self.quasiquote(args[0])
                } else {
                    Err(BadSyntax(SynQQuote, ~"bad number of arguments"))
                },
            SynUnquote => if args.len() == 1 {
                    self.unquote(args[0])
                } else {
                    Err(BadSyntax(SynUnquote, ~"bad number of arguments"))
                },
        }
    }

    fn call_proc(&mut self,
                anames: &~[@str],
                vargs: &Option<@str>,
                code: &~[@LDatum],
                &frame: &@mut Stack<LinearMap<@str, @LDatum>>,
                args: ~[@LDatum]) -> Result<@LDatum, RuntimeError>
    {
        // create new frame to store args
        let mut arg_frame = LinearMap::new();

        match *vargs {
            None => if args.len() != anames.len() {
                    return Err(ArgNumError(anames.len(), false, args.len()));
                },
            Some(vname) => if args.len() < anames.len() {
                    return Err(ArgNumError(anames.len(), true, args.len()));
                } else {
                    let vslice = vec::slice(args, anames.len(), args.len());
                    let va = do vec::foldr(vslice, @LNil) |&a, l| {
                        @LCons(a, l)
                    };
                    arg_frame.insert(vname, va);
                },
        }

        for uint::range(0, anames.len()) |i| {
            arg_frame.insert(anames[i], args[i]);
        }

        // store current env
        let old_env = self.env;

        // create new local env
        self.env = @mut push(frame, arg_frame);
        let mut res:Result<@LDatum, RuntimeError> = Err(NilEval);
        do code.each() |&val| {
            res = self.eval(val);
            res.is_ok()
        }

        // restore env
        self.env = old_env;

        res
    }

    fn call_prim(&mut self,
                f: PFunc,
                args: ~[@LDatum]) -> Result<@LDatum, RuntimeError>
    {
        match f {
            PEval => do call_prim1(args) |arg| {
                self.eval(arg)
            },
            PAdd => do call_num_foldl(args, zero()) |&lhs, &rhs| { Ok(lhs + rhs) },
            PSub => do call_num_foldl(args, one()) |&lhs, &rhs| { Ok(lhs - rhs) },
            PMul => do call_num_foldl(args, one()) |&lhs, &rhs| { Ok(lhs * rhs) },
            PDiv => do call_num_foldl(args, one()) |&lhs, &rhs| {
                if rhs.is_zero() {
                    Err(DivideByZeroError)
                } else {
                    Ok(lhs / rhs)
                }
            },
            PCar => do call_prim1(args) |arg| {
                match *arg {
                    LCons(h, _) => Ok(h),
                    _ => Err(TypeError),
                }
            },
            PCdr => do call_prim1(args) |arg| {
                match *arg {
                    LCons(_, t) => Ok(t),
                    _ => Err(TypeError),
                }
            },
            PEqv => do call_prim2(args) |arg1, arg2| {
                Ok(@LBool(arg1 == arg2))
            }
        }
    }

    fn recursive_qq(&mut self, val: @LDatum) -> Result<@LDatum, RuntimeError> {
        match *val {
            LCons(h,t) =>
                do result::chain(self.recursive_qq(h)) |qh| {
                    do result::map(&self.recursive_qq(t)) |&qt| {
                        @LCons(qh, qt)
                    }
                },
            LQQuote(v) =>
                do result::map(&self.quasiquote(v)) |&qv| {
                    @LQQuote(qv)
                },
            LUnquote(v) =>
                self.unquote(v),
            _ =>
                Ok(val),
        }
    }

    fn quasiquote(&mut self, val: @LDatum) -> Result<@LDatum, RuntimeError> {
        self.qq_lvl += 1;
        let res = self.recursive_qq(val);
        self.qq_lvl -= 1;
        res
    }

    fn unquote(&mut self, val: @LDatum) -> Result<@LDatum, RuntimeError> {
        if self.qq_lvl == 0 {
            Err(BadSyntax(SynUnquote, ~"unquote not nested in quasiquote"))
        } else {
            self.qq_lvl -= 1;
            let res =
            if self.qq_lvl == 0 {
                self.eval(val)
            } else {
                do result::map(&self.recursive_qq(val)) |&qval| {
                    @LUnquote(qval)
                }
            };
            self.qq_lvl += 1;
            res
        }
    }
}

priv fn find_var(env: @mut Stack<LinearMap<@str, @LDatum>>, name: &@str) -> Option<@LDatum> {
    let mut val: Option<@LDatum> = None;

    do env.each |frame| {
        match frame.find(name) {
            None => true,
            Some(v) => {
                val = Some(*v);
                false
            }
        }
    }

    val
}

priv fn set_var(env: @mut Stack<LinearMap<@str, @LDatum>>,
                name: &@str,
                val: @LDatum) -> bool {
    let mut success = false;

    do env.each_mut |frame| {
        match frame.find_mut(name) {
            None => (),
            Some(v) => {
                success = true;
                *v = val;
            }
        }
        !success
    }

    success
}

pub impl Runtime {
    fn new_std() -> Runtime {
        Runtime {
            stdin: io::stdin(),
            stdout: io::stdout(),
            stderr: io::stderr(),
            env: @mut push(&Stack::new(), load_prelude()),
            syntax: load_prelude_macro(),
            qq_lvl: 0,
        }
    }

    fn eval(&mut self, val: @LDatum) -> Result<@LDatum, RuntimeError>
    {
        match *val {
            LIdent(name) =>
                match find_var(self.env, &name) {
                    Some(datum) => Ok(datum),
                    None => Err(UnboundVariable(name)),
                },
            LCons(fexpr, aexpr) =>
                match aexpr.to_list() {
                    None => Err(NotList),
                    Some(aexprs) => {
                        match self.get_syntax(fexpr) {
                            Some(syntax) =>
                                self.run_syntax(syntax, aexprs),
                            None =>
                                match self.eval(fexpr) {
                                    Ok(@LPrim(f)) =>
                                        match result::map_vec(aexprs, |&expr| self.eval(expr))
                                        {
                                            Ok(args) => self.call_prim(f, args),
                                            Err(e) => Err(e),
                                        },
                                    Ok(@LProc(ref anames, ref vargs, ref code, ref env)) =>
                                        match result::map_vec(aexprs, |&expr| self.eval(expr))
                                        {
                                            Ok(args) =>
                                                self.call_proc(anames, vargs, code, env, args),
                                            Err(e) =>
                                                Err(e),
                                        },
                                    Ok(_) => Err(NotCallable),
                                    Err(e) => Err(e),
                                },
                        }
                    },
                },
            LQuote(val) => Ok(val),
            LQQuote(val) => self.quasiquote(val),
            LUnquote(val) => self.unquote(val),
            LNil => Err(NilEval),
            _ => Ok(val),
        }
    }
}
<commit_msg>define is global<commit_after>use datum::*;
use primitive::*;
use numeric::LNumeric;
use core::num::Zero::zero;
use core::num::One::one;
use core::hashmap::linear::LinearMap;
use stack::*;

struct Runtime {
    stdin: @io::Reader,
    stdout: @io::Writer,
    stderr: @io::Writer,
    env: @mut Stack<LinearMap<@str, @LDatum>>,
    global: LinearMap<@str, Either<@LDatum, PrimSyntax>>,
    qq_lvl: uint,
}

#[deriving(Eq)]
enum RuntimeError {
    UnboundVariable(@str),
    RefMacro(@str),
    NotCallable,
    NotList,
    ArgNumError(uint, bool, uint),
    TypeError,
    DivideByZeroError,
    NilEval,
    BadSyntax(PrimSyntax, ~str),
}

impl ToStr for RuntimeError {
    fn to_str(&self) -> ~str {
        err_to_str(self)
    }
}

priv fn err_to_str(&err: &RuntimeError) -> ~str {
    match err {
        UnboundVariable(name) => ~"unbound variable: " + name,
        RefMacro(name) => ~"cannot reference macro name: " + name,
        NotCallable => ~"not callable",
        NotList => ~"not list",
        ArgNumError(expected, false, argnum) => {
            fmt!("expected %u arguments, but found %u arguments", expected, argnum)
        },
        ArgNumError(expected, true, argnum) => {
            fmt!("expected %u or more arguments, but found %u arguments", expected, argnum)
        },
        TypeError => ~"type error",
        DivideByZeroError => ~"divide by zero",
        NilEval => ~"() cannot be evaluated",
        BadSyntax(syn, reason) => ~"bad syntax for " + syn.to_str() + ": " + reason,
    }
}

fn load_prelude() -> LinearMap<@str, Either<@LDatum, PrimSyntax>> {
    let mut map = LinearMap::new();
    for vec::each(prelude()) |&pair| {
        let (key, func) = pair;
        map.insert(key, Left(@LPrim(func)));
    }
    for vec::each(syntax_prelude()) |&pair| {
        let (key, syntax) = pair;
        map.insert(key, Right(syntax));
    }
    map
}

priv fn call_prim1(args: ~[@LDatum],
                op: &fn(@LDatum) -> Result<@LDatum, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    if args.len() == 1 {
        op(args[0])
    } else {
        Err(ArgNumError(1, false, args.len()))
    }
}

priv fn call_prim2(args: ~[@LDatum],
                op: &fn(@LDatum, @LDatum) -> Result<@LDatum, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    if args.len() == 2 {
        op(args[0], args[1])
    } else {
        Err(ArgNumError(2, false, args.len()))
    }
}

priv fn call_num_prim2(args: ~[@LDatum],
                    op: &fn(&LNumeric, &LNumeric) -> Result<@LDatum, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    if args.len() == 2 {
        match *args[0] {
            LNum(lhs) => match *args[1] {
                LNum(rhs) => op(&lhs, &rhs),
                _ => Err(TypeError),
            },
            _ => Err(TypeError),
        }
    } else {
        Err(ArgNumError(2, false, args.len()))
    }
}

priv fn call_num_foldl(args: ~[@LDatum],
                    a0: LNumeric,
                    op: &fn(&LNumeric, &LNumeric) -> Result<LNumeric, RuntimeError>)
    -> Result<@LDatum, RuntimeError>
{
    let mut res = a0;
    let mut err = false;
    do args.each |&arg| {
        match *arg {
            LNum(a) => {
                match op(&res, &a) {
                    Ok(n) => {
                        res = n;
                        err = false;
                    },
                    _ => {
                        err = true;
                    }
                }
            },
            _ => {
                err = true;
            }
        }
        !err
    }
    if err {
        Err(TypeError)
    } else {
        Ok(@LNum(res))
    }
}

priv fn get_syms(&arg: &@LDatum) -> Result<(~[@str], Option<@str>), ~str> {
    let mut iter = arg;
    let mut args : ~[@str] = ~[];
    let mut varargs : Option<@str> = None;

    loop {
        match *iter {
            LCons(h, t) => match *h {
                LIdent(name) => {
                    args.push(name);
                    iter = t;
                },
                _ => {
                    return Err(~"non-symbol argument");
                }
            },
            LIdent(name) => {
                varargs = Some(name);
                break;
            },
            LNil => {
                break;
            },
            _ => {
                return Err(~"non-list argument");
            },
        }
    }

    Ok((args, varargs))
}

priv impl Runtime {
    fn get_syntax(&self, val: @LDatum) -> Option<PrimSyntax> {
        match *val {
            LIdent(name) => match self.global.find(&name) {
                Some(&Right(syn)) => Some(syn),
                _ => None,
            },
            _ => None,
        }
    }

    fn find_var(&self, name: &@str) -> Result<@LDatum, RuntimeError> {
        let mut val: Option<@LDatum> = None;

        do self.env.each |frame| {
            match frame.find(name) {
                None => true,
                Some(v) => {
                    val = Some(*v);
                    false
                }
            }
        }

        match val {
            None => match self.global.find(name) {
                Some(&Left(v)) => Ok(v),
                Some(&Right(_)) => Err(RefMacro(*name)),
                None => Err(UnboundVariable(*name)),
            },
            Some(v) => Ok(v),
        }
    }

    fn run_syntax(&mut self,
                syn: PrimSyntax,
                args: ~[@LDatum]) -> Result<@LDatum, RuntimeError>
    {
        match syn {
            SynIf => if args.len() == 3 {
                    do result::chain(self.eval(args[0])) |cond| {
                        match *cond {
                            LBool(true) => self.eval(args[1]),
                            LBool(false) => self.eval(args[2]),
                            _ => Err(TypeError),
                        }
                    }
                } else {
                    Err(BadSyntax(SynIf, ~"bad number of arguments"))
                },
            SynLambda => if args.len() < 2 {
                    Err(BadSyntax(SynLambda, ~"no body given"))
                } else {
                    match get_syms(&args[0]) {
                        Err(e) => Err(BadSyntax(SynLambda, e)),
                        Ok((anames, varargs)) => {
                            let seq = vec::from_slice(vec::slice(args, 1, args.len()));
                            Ok(@LProc(anames, varargs, seq, self.env))
                        },
                    }
                },
            SynDefine => if args.len() < 2 {
                    Err(BadSyntax(SynDefine, ~"no body given"))
                } else {
                    match get_syms(&args[0]) {
                        Err(e) => Err(BadSyntax(SynDefine, e)),
                        Ok((anames, varargs)) =>
                            if anames.is_empty() {
                                match varargs {
                                    None => Err(BadSyntax(SynDefine, ~"name not given")),
                                    Some(name) => if args.len() != 2 {
                                            Err(BadSyntax(SynDefine, ~"multiple expressions"))
                                        } else {
                                            do result::map(&self.eval(args[1])) |&val| {
                                                self.global.insert(name, Left(val));
                                                @LNil
                                            }
                                        }
                                }
                            } else {
                                let name = anames[0];
                                let anames = vec::from_slice(vec::slice(anames, 1, anames.len()));
                                let seq = vec::from_slice(vec::slice(args, 1, args.len()));
                                let proc = @LProc(anames, varargs, seq, self.env);
                                self.global.insert(name, Left(proc));
                                Ok(@LNil)
                            }
                    }
                },
            SynSet => if args.len() != 2 {
                    Err(BadSyntax(SynSet, ~"bad number of arguments"))
                } else {
                    match *args[0] {
                        LIdent(name) => do result::chain(self.eval(args[1])) |val| {
                            if set_var(self.env, &name, val) {
                                Ok(@LNil)
                            } else {
                                Err(BadSyntax(SynSet, ~"unbound variable"))
                            }
                        },
                        _ => Err(BadSyntax(SynSet, ~"cannot set non-variable"))
                    }
                },
            SynQuote => if args.len() == 1 {
                    Ok(args[0])
                } else {
                    Err(BadSyntax(SynQuote, ~"bad number of arguments"))
                },
            SynQQuote => if args.len() == 1 {
                    self.quasiquote(args[0])
                } else {
                    Err(BadSyntax(SynQQuote, ~"bad number of arguments"))
                },
            SynUnquote => if args.len() == 1 {
                    self.unquote(args[0])
                } else {
                    Err(BadSyntax(SynUnquote, ~"bad number of arguments"))
                },
        }
    }

    fn call_proc(&mut self,
                anames: &~[@str],
                vargs: &Option<@str>,
                code: &~[@LDatum],
                &frame: &@mut Stack<LinearMap<@str, @LDatum>>,
                args: ~[@LDatum]) -> Result<@LDatum, RuntimeError>
    {
        // create new frame to store args
        let mut arg_frame = LinearMap::new();

        match *vargs {
            None => if args.len() != anames.len() {
                    return Err(ArgNumError(anames.len(), false, args.len()));
                },
            Some(vname) => if args.len() < anames.len() {
                    return Err(ArgNumError(anames.len(), true, args.len()));
                } else {
                    let vslice = vec::slice(args, anames.len(), args.len());
                    let va = do vec::foldr(vslice, @LNil) |&a, l| {
                        @LCons(a, l)
                    };
                    arg_frame.insert(vname, va);
                },
        }

        for uint::range(0, anames.len()) |i| {
            arg_frame.insert(anames[i], args[i]);
        }

        // store current env
        let old_env = self.env;

        // create new local env
        self.env = @mut push(frame, arg_frame);
        let mut res:Result<@LDatum, RuntimeError> = Err(NilEval);
        do code.each() |&val| {
            res = self.eval(val);
            res.is_ok()
        }

        // restore env
        self.env = old_env;

        res
    }

    fn call_prim(&mut self,
                f: PFunc,
                args: ~[@LDatum]) -> Result<@LDatum, RuntimeError>
    {
        match f {
            PEval => do call_prim1(args) |arg| {
                self.eval(arg)
            },
            PAdd => do call_num_foldl(args, zero()) |&lhs, &rhs| { Ok(lhs + rhs) },
            PSub => do call_num_foldl(args, one()) |&lhs, &rhs| { Ok(lhs - rhs) },
            PMul => do call_num_foldl(args, one()) |&lhs, &rhs| { Ok(lhs * rhs) },
            PDiv => do call_num_foldl(args, one()) |&lhs, &rhs| {
                if rhs.is_zero() {
                    Err(DivideByZeroError)
                } else {
                    Ok(lhs / rhs)
                }
            },
            PCar => do call_prim1(args) |arg| {
                match *arg {
                    LCons(h, _) => Ok(h),
                    _ => Err(TypeError),
                }
            },
            PCdr => do call_prim1(args) |arg| {
                match *arg {
                    LCons(_, t) => Ok(t),
                    _ => Err(TypeError),
                }
            },
            PEqv => do call_prim2(args) |arg1, arg2| {
                Ok(@LBool(arg1 == arg2))
            }
        }
    }

    fn recursive_qq(&mut self, val: @LDatum) -> Result<@LDatum, RuntimeError> {
        match *val {
            LCons(h,t) =>
                do result::chain(self.recursive_qq(h)) |qh| {
                    do result::map(&self.recursive_qq(t)) |&qt| {
                        @LCons(qh, qt)
                    }
                },
            LQQuote(v) =>
                do result::map(&self.quasiquote(v)) |&qv| {
                    @LQQuote(qv)
                },
            LUnquote(v) =>
                self.unquote(v),
            _ =>
                Ok(val),
        }
    }

    fn quasiquote(&mut self, val: @LDatum) -> Result<@LDatum, RuntimeError> {
        self.qq_lvl += 1;
        let res = self.recursive_qq(val);
        self.qq_lvl -= 1;
        res
    }

    fn unquote(&mut self, val: @LDatum) -> Result<@LDatum, RuntimeError> {
        if self.qq_lvl == 0 {
            Err(BadSyntax(SynUnquote, ~"unquote not nested in quasiquote"))
        } else {
            self.qq_lvl -= 1;
            let res =
            if self.qq_lvl == 0 {
                self.eval(val)
            } else {
                do result::map(&self.recursive_qq(val)) |&qval| {
                    @LUnquote(qval)
                }
            };
            self.qq_lvl += 1;
            res
        }
    }
}

priv fn set_var(env: @mut Stack<LinearMap<@str, @LDatum>>,
                name: &@str,
                val: @LDatum) -> bool {
    let mut success = false;

    do env.each_mut |frame| {
        match frame.find_mut(name) {
            None => (),
            Some(v) => {
                success = true;
                *v = val;
            }
        }
        !success
    }

    success
}

pub impl Runtime {
    fn new_std() -> Runtime {
        Runtime {
            stdin: io::stdin(),
            stdout: io::stdout(),
            stderr: io::stderr(),
            env: @mut Stack::new(),
            global: load_prelude(),
            qq_lvl: 0,
        }
    }

    fn eval(&mut self, val: @LDatum) -> Result<@LDatum, RuntimeError>
    {
        match *val {
            LIdent(name) => self.find_var(&name),
            LCons(fexpr, aexpr) =>
                match aexpr.to_list() {
                    None => Err(NotList),
                    Some(aexprs) => {
                        match self.get_syntax(fexpr) {
                            Some(syntax) =>
                                self.run_syntax(syntax, aexprs),
                            None =>
                                match self.eval(fexpr) {
                                    Ok(@LPrim(f)) =>
                                        match result::map_vec(aexprs, |&expr| self.eval(expr))
                                        {
                                            Ok(args) => self.call_prim(f, args),
                                            Err(e) => Err(e),
                                        },
                                    Ok(@LProc(ref anames, ref vargs, ref code, ref env)) =>
                                        match result::map_vec(aexprs, |&expr| self.eval(expr))
                                        {
                                            Ok(args) =>
                                                self.call_proc(anames, vargs, code, env, args),
                                            Err(e) =>
                                                Err(e),
                                        },
                                    Ok(_) => Err(NotCallable),
                                    Err(e) => Err(e),
                                },
                        }
                    },
                },
            LQuote(val) => Ok(val),
            LQQuote(val) => self.quasiquote(val),
            LUnquote(val) => self.unquote(val),
            LNil => Err(NilEval),
            _ => Ok(val),
        }
    }
}
<|endoftext|>


<commit_before>#[derive(Debug)]
pub struct Brackets {
    brackets: String,
}

impl Brackets {
    pub fn from(text: &str) -> Self {
        Brackets {
            brackets: text.chars()
                .filter(|&x| {
                    x == '[' || x == ']' || x == '{' || x == '}' || x == '(' || x == ')'
                })
                .collect(),
        }
    }

    pub fn are_balanced(&self) -> bool {
        let mut r = Vec::new();

        for c in self.brackets.chars() {
            match c {
                '[' | '{' | '(' => r.push(c),
                ')' => if let Some(l) = r.pop() {
                    if l != '(' {
                        return false;
                    }
                } else {
                    return false;
                },
                ']' | '}' => if let Some(l) = r.pop() {
                    if c as i32 - l as i32 != 2 {
                        return false;
                    }
                } else {
                    return false;
                },
                _ => return false,
            }
        }

        r.is_empty()
    }
}
<commit_msg>Clean up rust code for bracket-push case<commit_after>#[derive(Debug)]
pub struct Brackets {
    string: String,
}

impl Brackets {
    pub fn from(text: &str) -> Self {
        Brackets {
            string: text.to_string(),
        }
    }

    pub fn are_balanced(&self) -> bool {
        let mut r = Vec::new();

        for c in self.string.chars() {
            match c {
                '[' | '{' | '(' => r.push(c),
                ']' | '}' | ')' => match (r.pop(), c) {
                    (Some('{'), '}') | (Some('['), ']') | (Some('('), ')') => {}
                    _ => return false,
                },
                _ => {}
            }
        }

        r.is_empty()
    }
}
<|endoftext|>


<commit_before>use schema::*;
use diesel::*;

#[test]
fn filter_by_int_equality() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean_id = find_user_by_name("Sean", &connection).id;
    let tess_id = find_user_by_name("Tess", &connection).id;
    let unused_id = sean_id + tess_id;

    let sean = User::new(sean_id, "Sean");
    let tess = User::new(tess_id, "Tess");
    assert_eq!(Ok(sean), users.filter(id.eq(sean_id)).first(&connection));
    assert_eq!(Ok(tess), users.filter(id.eq(tess_id)).first(&connection));
    assert_eq!(Err(NotFound), users.filter(id.eq(unused_id)).first::<User>(&connection));
}

#[test]
fn filter_by_string_equality() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();

    let sean = User::new(1, "Sean");
    let tess = User::new(2, "Tess");
    assert_eq!(Ok(sean), users.filter(name.eq("Sean")).first(&connection));
    assert_eq!(Ok(tess), users.filter(name.eq("Tess")).first(&connection));
    assert_eq!(Err(NotFound), users.filter(name.eq("Jim")).first::<User>(&connection));
}

#[test]
fn filter_by_equality_on_nullable_columns() {
    use schema::users::dsl::*;

    let connection = connection();
    let data = vec![
        NewUser::new("Sean", Some("black")),
        NewUser::new("Tess", Some("brown")),
        NewUser::new("Jim", Some("black")),
    ];
    insert(&data).into(users).execute(&connection).unwrap();

    let data = users.order(id).load::<User>(&connection).unwrap();
    let sean = data[0].clone();
    let tess = data[1].clone();
    let jim = data[2].clone();

    let source = users.filter(hair_color.eq("black"));
    assert_eq!(vec![sean, jim], source.order(id).load(&connection).unwrap());
    let source = users.filter(hair_color.eq("brown"));
    assert_eq!(vec![tess], source.load(&connection).unwrap());
}

#[test]
fn filter_by_is_not_null_on_nullable_columns() {
    use schema::users::dsl::*;

    let connection = connection();
    let data = vec![
        NewUser::new("Derek", Some("red")),
        NewUser::new("Gordon", None),
    ];
    insert(&data).into(users).execute(&connection).unwrap();
    let data = users.order(id).load::<User>(&connection).unwrap();
    let derek = data[0].clone();

    let source = users.filter(hair_color.is_not_null());
    assert_eq!(vec![derek], source.load(&connection).unwrap());
}

#[test]
fn filter_by_is_null_on_nullable_columns() {
    use schema::users::dsl::*;

    let connection = connection();
    let data = vec![
        NewUser::new("Derek", Some("red")),
        NewUser::new("Gordon", None),
    ];
    insert(&data).into(users).execute(&connection).unwrap();
    let data = users.order(id).load::<User>(&connection).unwrap();
    let gordon = data[1].clone();

    let source = users.filter(hair_color.is_null());
    assert_eq!(vec![gordon], source.load(&connection).unwrap());
}

#[test]
fn filter_after_joining() {
    use schema::users::name;

    let connection = connection_with_sean_and_tess_in_users_table();
    connection.execute("INSERT INTO posts (id, title, user_id) VALUES
                       (1, 'Hello', 1), (2, 'World', 2)")
        .unwrap();

    let sean = User::new(1, "Sean");
    let tess = User::new(2, "Tess");
    let seans_post = Post::new(1, 1, "Hello", None);
    let tess_post = Post::new(2, 2, "World", None);
    let source = users::table.inner_join(posts::table);
    assert_eq!(Ok((sean, seans_post)),
        source.filter(name.eq("Sean")).first(&connection));
    assert_eq!(Ok((tess, tess_post)),
        source.filter(name.eq("Tess")).first(&connection));
    assert_eq!(Err(NotFound),
        source.filter(name.eq("Jim")).first::<(User, Post)>(&connection));
}

#[test]
fn select_then_filter() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();

    let source = users.select(name);
    assert_eq!(Ok("Sean".to_string()),
        source.filter(name.eq("Sean")).first(&connection));
    assert_eq!(Ok("Tess".to_string()),
        source.filter(name.eq("Tess")).first(&connection));
    assert_eq!(Err(NotFound), source.filter(name.eq("Jim")).first::<String>(&connection));
}

#[test]
fn filter_then_select() {
    use schema::users::dsl::*;

    let connection = connection();
    let data = vec![NewUser::new("Sean", None), NewUser::new("Tess", None)];
    insert(&data).into(users).execute(&connection).unwrap();

    assert_eq!(Ok("Sean".to_string()),
        users.filter(name.eq("Sean")).select(name).first(&connection));
    assert_eq!(Ok("Tess".to_string()),
        users.filter(name.eq("Tess")).select(name).first(&connection));
    assert_eq!(Err(NotFound), users.filter(name.eq("Jim")).select(name)
                                   .first::<String>(&connection));
}

#[test]
fn filter_on_multiple_columns() {
    use schema::users::dsl::*;

    let connection = connection();
    let data: &[_] = &[
        NewUser::new("Sean", Some("black")),
        NewUser::new("Sean", Some("brown")),
        NewUser::new("Sean", None),
        NewUser::new("Tess", Some("black")),
        NewUser::new("Tess", Some("brown")),
    ];
    insert(data).into(users).execute(&connection).unwrap();
    let data = users.order(id).load::<User>(&connection).unwrap();
    let black_haired_sean = data[0].clone();
    let brown_haired_sean = data[1].clone();
    let black_haired_tess = data[3].clone();
    let brown_haired_tess = data[4].clone();

    let source = users.filter(name.eq("Sean").and(hair_color.eq("black")));
    assert_eq!(vec![black_haired_sean], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Sean").and(hair_color.eq("brown")));
    assert_eq!(vec![brown_haired_sean], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Tess").and(hair_color.eq("black")));
    assert_eq!(vec![black_haired_tess], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Tess").and(hair_color.eq("brown")));
    assert_eq!(vec![brown_haired_tess], source.load(&connection).unwrap());
}

#[test]
fn filter_called_twice_means_same_thing_as_and() {
    use schema::users::dsl::*;

    let connection = connection();
    let data: &[_] = &[
        NewUser::new("Sean", Some("black")),
        NewUser::new("Sean", Some("brown")),
        NewUser::new("Sean", None),
        NewUser::new("Tess", Some("black")),
        NewUser::new("Tess", Some("brown")),
    ];
    insert(data).into(users).execute(&connection).unwrap();
    let data = users.order(id).load::<User>(&connection).unwrap();
    let black_haired_sean = data[0].clone();
    let brown_haired_sean = data[1].clone();
    let black_haired_tess = data[3].clone();
    let brown_haired_tess = data[4].clone();

    let source = users.filter(name.eq("Sean")).filter(hair_color.eq("black"));
    assert_eq!(vec![black_haired_sean], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Sean")).filter(hair_color.eq("brown"));
    assert_eq!(vec![brown_haired_sean], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Tess")).filter(hair_color.eq("black"));
    assert_eq!(vec![black_haired_tess], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Tess")).filter(hair_color.eq("brown"));
    assert_eq!(vec![brown_haired_tess], source.load(&connection).unwrap());
}

table! {
    points (x) {
        x -> Integer,
        y -> Integer,
    }
}

#[test]
fn filter_on_column_equality() {
    use self::points::dsl::*;

    let connection = connection();
    connection.execute("INSERT INTO points (x, y) VALUES (1, 1), (1, 2), (2, 2)").unwrap();

    let expected_data = vec![(1, 1), (2, 2)];
    let query = points.order(x).filter(x.eq(y));
    let data: Vec<_> = query.load(&connection).unwrap();
    assert_eq!(expected_data, data);
}

#[test]
fn filter_with_or() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    insert(&NewUser::new("Jim", None)).into(users).execute(&connection).unwrap();

    let expected_users = vec![User::new(1, "Sean"), User::new(2, "Tess")];
    let data: Vec<_> = users.order(id)
        .filter(name.eq("Sean").or(name.eq("Tess")))
        .load(&connection).unwrap();

    assert_eq!(expected_users, data);
}

#[test]
fn or_doesnt_mess_with_precidence_of_previous_statements() {
    use schema::users::dsl::*;
    use diesel::expression::AsExpression;

    let connection = connection_with_sean_and_tess_in_users_table();
    let f = AsExpression::<types::Bool>::as_expression(false);
    let count = users.filter(f).filter(f.or(true))
        .count().first(&connection);

    assert_eq!(Ok(0), count);

    let count = users.filter(f.or(f).and(f.or(true)))
        .count().first(&connection);

    assert_eq!(Ok(0), count);
}

use diesel::types::VarChar;
sql_function!(lower, lower_t, (x: VarChar) -> VarChar);

#[test]
fn filter_by_boxed_predicate() {
    fn by_name(name: &str) -> Box<BoxableExpression<users::table, TestBackend, SqlType=types::Bool>> {
        Box::new(lower(users::name).eq(name.to_string()))
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = User::new(1, "Sean");
    let tess = User::new(2, "Tess");
    let queried_sean = users::table.filter(by_name("sean")).first(&connection);
    let queried_tess = users::table.filter(by_name("tess")).first(&connection);

    assert_eq!(Ok(sean), queried_sean);
    assert_eq!(Ok(tess), queried_tess);
}
<commit_msg>Fix result set ordering in filter tests (#753)<commit_after>use schema::*;
use diesel::*;

macro_rules! assert_sets_eq {
    ($set1:expr, $set2:expr) => {
        let set1 = {$set1};
        let set2 = {$set2};
        let s1r : Vec<_> = set1.iter().filter(|&si| !set2.contains(si)).collect();
        assert!(s1r.len() == 0, format!("left set contains items not found in right set: {:?}", s1r));
        let s2r : Vec<_> = set2.iter().filter(|&si| !set1.contains(si)).collect();
        assert!(s2r.len() == 0, format!("right set contains items not found in left set: {:?}", s2r));
    };
}

#[test]
fn filter_by_int_equality() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean_id = find_user_by_name("Sean", &connection).id;
    let tess_id = find_user_by_name("Tess", &connection).id;
    let unused_id = sean_id + tess_id;

    let sean = User::new(sean_id, "Sean");
    let tess = User::new(tess_id, "Tess");
    assert_eq!(Ok(sean), users.filter(id.eq(sean_id)).first(&connection));
    assert_eq!(Ok(tess), users.filter(id.eq(tess_id)).first(&connection));
    assert_eq!(Err(NotFound), users.filter(id.eq(unused_id)).first::<User>(&connection));
}

#[test]
fn filter_by_string_equality() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();

    let sean = User::new(1, "Sean");
    let tess = User::new(2, "Tess");
    assert_eq!(Ok(sean), users.filter(name.eq("Sean")).first(&connection));
    assert_eq!(Ok(tess), users.filter(name.eq("Tess")).first(&connection));
    assert_eq!(Err(NotFound), users.filter(name.eq("Jim")).first::<User>(&connection));
}

#[test]
fn filter_by_equality_on_nullable_columns() {
    use schema::users::dsl::*;

    let connection = connection();
    let data = vec![
        NewUser::new("Sean", Some("black")),
        NewUser::new("Tess", Some("brown")),
        NewUser::new("Jim", Some("black")),
    ];
    insert(&data).into(users).execute(&connection).unwrap();

    let data = users.order(id).load::<User>(&connection).unwrap();
    let sean = data[0].clone();
    let tess = data[1].clone();
    let jim = data[2].clone();

    let source = users.filter(hair_color.eq("black"));
    assert_sets_eq!(vec![sean, jim], source.load(&connection).unwrap());

    let source = users.filter(hair_color.eq("brown"));
    assert_eq!(vec![tess], source.load(&connection).unwrap());
}

#[test]
fn filter_by_is_not_null_on_nullable_columns() {
    use schema::users::dsl::*;

    let connection = connection();
    let data = vec![
        NewUser::new("Derek", Some("red")),
        NewUser::new("Gordon", None),
    ];
    insert(&data).into(users).execute(&connection).unwrap();
    let data = users.order(id).load::<User>(&connection).unwrap();
    let derek = data[0].clone();

    let source = users.filter(hair_color.is_not_null());
    assert_eq!(vec![derek], source.load(&connection).unwrap());
}

#[test]
fn filter_by_is_null_on_nullable_columns() {
    use schema::users::dsl::*;

    let connection = connection();
    let data = vec![
        NewUser::new("Derek", Some("red")),
        NewUser::new("Gordon", None),
    ];
    insert(&data).into(users).execute(&connection).unwrap();
    let data = users.order(id).load::<User>(&connection).unwrap();
    let gordon = data[1].clone();

    let source = users.filter(hair_color.is_null());
    assert_eq!(vec![gordon], source.load(&connection).unwrap());
}

#[test]
fn filter_after_joining() {
    use schema::users::name;

    let connection = connection_with_sean_and_tess_in_users_table();
    connection.execute("INSERT INTO posts (id, title, user_id) VALUES
                       (1, 'Hello', 1), (2, 'World', 2)")
        .unwrap();

    let sean = User::new(1, "Sean");
    let tess = User::new(2, "Tess");
    let seans_post = Post::new(1, 1, "Hello", None);
    let tess_post = Post::new(2, 2, "World", None);
    let source = users::table.inner_join(posts::table);
    assert_eq!(Ok((sean, seans_post)),
        source.filter(name.eq("Sean")).first(&connection));
    assert_eq!(Ok((tess, tess_post)),
        source.filter(name.eq("Tess")).first(&connection));
    assert_eq!(Err(NotFound),
        source.filter(name.eq("Jim")).first::<(User, Post)>(&connection));
}

#[test]
fn select_then_filter() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();

    let source = users.select(name);
    assert_eq!(Ok("Sean".to_string()),
        source.filter(name.eq("Sean")).first(&connection));
    assert_eq!(Ok("Tess".to_string()),
        source.filter(name.eq("Tess")).first(&connection));
    assert_eq!(Err(NotFound), source.filter(name.eq("Jim")).first::<String>(&connection));
}

#[test]
fn filter_then_select() {
    use schema::users::dsl::*;

    let connection = connection();
    let data = vec![NewUser::new("Sean", None), NewUser::new("Tess", None)];
    insert(&data).into(users).execute(&connection).unwrap();

    assert_eq!(Ok("Sean".to_string()),
        users.filter(name.eq("Sean")).select(name).first(&connection));
    assert_eq!(Ok("Tess".to_string()),
        users.filter(name.eq("Tess")).select(name).first(&connection));
    assert_eq!(Err(NotFound), users.filter(name.eq("Jim")).select(name)
                                   .first::<String>(&connection));
}

#[test]
fn filter_on_multiple_columns() {
    use schema::users::dsl::*;

    let connection = connection();
    let data: &[_] = &[
        NewUser::new("Sean", Some("black")),
        NewUser::new("Sean", Some("brown")),
        NewUser::new("Sean", None),
        NewUser::new("Tess", Some("black")),
        NewUser::new("Tess", Some("brown")),
    ];
    insert(data).into(users).execute(&connection).unwrap();
    let data = users.order(id).load::<User>(&connection).unwrap();
    let black_haired_sean = data[0].clone();
    let brown_haired_sean = data[1].clone();
    let black_haired_tess = data[3].clone();
    let brown_haired_tess = data[4].clone();

    let source = users.filter(name.eq("Sean").and(hair_color.eq("black")));
    assert_eq!(vec![black_haired_sean], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Sean").and(hair_color.eq("brown")));
    assert_eq!(vec![brown_haired_sean], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Tess").and(hair_color.eq("black")));
    assert_eq!(vec![black_haired_tess], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Tess").and(hair_color.eq("brown")));
    assert_eq!(vec![brown_haired_tess], source.load(&connection).unwrap());
}

#[test]
fn filter_called_twice_means_same_thing_as_and() {
    use schema::users::dsl::*;

    let connection = connection();
    let data: &[_] = &[
        NewUser::new("Sean", Some("black")),
        NewUser::new("Sean", Some("brown")),
        NewUser::new("Sean", None),
        NewUser::new("Tess", Some("black")),
        NewUser::new("Tess", Some("brown")),
    ];
    insert(data).into(users).execute(&connection).unwrap();
    let data = users.order(id).load::<User>(&connection).unwrap();
    let black_haired_sean = data[0].clone();
    let brown_haired_sean = data[1].clone();
    let black_haired_tess = data[3].clone();
    let brown_haired_tess = data[4].clone();

    let source = users.filter(name.eq("Sean")).filter(hair_color.eq("black"));
    assert_eq!(vec![black_haired_sean], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Sean")).filter(hair_color.eq("brown"));
    assert_eq!(vec![brown_haired_sean], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Tess")).filter(hair_color.eq("black"));
    assert_eq!(vec![black_haired_tess], source.load(&connection).unwrap());

    let source = users.filter(name.eq("Tess")).filter(hair_color.eq("brown"));
    assert_eq!(vec![brown_haired_tess], source.load(&connection).unwrap());
}

table! {
    points (x) {
        x -> Integer,
        y -> Integer,
    }
}

#[test]
fn filter_on_column_equality() {
    use self::points::dsl::*;

    let connection = connection();
    connection.execute("INSERT INTO points (x, y) VALUES (1, 1), (1, 2), (2, 2)").unwrap();

    let expected_data = vec![(1, 1), (2, 2)];
    let query = points.order(x).filter(x.eq(y));
    let data: Vec<_> = query.load(&connection).unwrap();
    assert_sets_eq!(expected_data, data);
}

#[test]
fn filter_with_or() {
    use schema::users::dsl::*;

    let connection = connection_with_sean_and_tess_in_users_table();
    insert(&NewUser::new("Jim", None)).into(users).execute(&connection).unwrap();

    let expected_users = vec![User::new(1, "Sean"), User::new(2, "Tess")];
    let data: Vec<_> = users.order(id)
        .filter(name.eq("Sean").or(name.eq("Tess")))
        .load(&connection).unwrap();

    assert_sets_eq!(expected_users, data);
}

#[test]
fn or_doesnt_mess_with_precidence_of_previous_statements() {
    use schema::users::dsl::*;
    use diesel::expression::AsExpression;

    let connection = connection_with_sean_and_tess_in_users_table();
    let f = AsExpression::<types::Bool>::as_expression(false);
    let count = users.filter(f).filter(f.or(true))
        .count().first(&connection);

    assert_eq!(Ok(0), count);

    let count = users.filter(f.or(f).and(f.or(true)))
        .count().first(&connection);

    assert_eq!(Ok(0), count);
}

use diesel::types::VarChar;
sql_function!(lower, lower_t, (x: VarChar) -> VarChar);

#[test]
fn filter_by_boxed_predicate() {
    fn by_name(name: &str) -> Box<BoxableExpression<users::table, TestBackend, SqlType=types::Bool>> {
        Box::new(lower(users::name).eq(name.to_string()))
    }

    let connection = connection_with_sean_and_tess_in_users_table();
    let sean = User::new(1, "Sean");
    let tess = User::new(2, "Tess");
    let queried_sean = users::table.filter(by_name("sean")).first(&connection);
    let queried_tess = users::table.filter(by_name("tess")).first(&connection);

    assert_eq!(Ok(sean), queried_sean);
    assert_eq!(Ok(tess), queried_tess);
}
<|endoftext|>


<commit_before>use rusqlite::Connection;
use std::result;
use log;

#[derive(Debug)]
pub struct JobRequireVariable {
    id: i32,
    fk_job: i32,
    fk_variable: i32,
}

pub fn table_create_job_require_variable(conn: &Connection) {
    conn.execute(
        "CREATE TABLE JOB_REQUIRE_VARIABLE (
                  id                    INTEGER PRIMARY KEY ASC,
                  fk_job                INTEGER NOT NULL,
                  fk_variable           INTEGER NOT NULL,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable) REFERENCES JOB_REQUIRE_VARIABLE(id) ON UPDATE CASCADE
                  )",
        &[],
    ).unwrap();
}

pub fn insert_job_require_variable(
    conn: &Connection,
    job: &i32,
    variable: &i32,
) -> Result<i32, &'static str> {
    let me = JobRequireVariable {
        id: 0,
        fk_job: *job,
        fk_variable: *variable,
    };
    let job_require_variable_instance = conn.execute(
        "INSERT INTO JOB_REQUIRE_VARIABLE (fk_job, fk_variable)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_variable],
    );
    if job_require_variable_instance.is_err() {
        return Err("Insert failed");
    }
    job_require_variable_instance.unwrap();
    return Ok(0);
}

pub fn list_job_require_variable(conn: &Connection) -> Vec<JobRequireVariable> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    let mut items = Vec::<JobRequireVariable>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_require_variable_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found job_require_variable {:?}", person.unwrap());
    }
}

pub fn pk_job_require_variable_by_name(
    conn: &Connection,
    job: &i32,
    variable: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE WHERE fk_job = ?1 AND fk_variable = ?2").unwrap();
    let job_require_variable_iter = stmt.query_map(&[job, variable], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    if job_require_variable_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = job_require_variable_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<commit_msg>Remoive unused 'use'<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobRequireVariable {
    id: i32,
    fk_job: i32,
    fk_variable: i32,
}

pub fn table_create_job_require_variable(conn: &Connection) {
    conn.execute(
        "CREATE TABLE JOB_REQUIRE_VARIABLE (
                  id                    INTEGER PRIMARY KEY ASC,
                  fk_job                INTEGER NOT NULL,
                  fk_variable           INTEGER NOT NULL,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable) REFERENCES JOB_REQUIRE_VARIABLE(id) ON UPDATE CASCADE
                  )",
        &[],
    ).unwrap();
}

pub fn insert_job_require_variable(
    conn: &Connection,
    job: &i32,
    variable: &i32,
) -> Result<i32, &'static str> {
    let me = JobRequireVariable {
        id: 0,
        fk_job: *job,
        fk_variable: *variable,
    };
    let job_require_variable_instance = conn.execute(
        "INSERT INTO JOB_REQUIRE_VARIABLE (fk_job, fk_variable)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_variable],
    );
    if job_require_variable_instance.is_err() {
        return Err("Insert failed");
    }
    job_require_variable_instance.unwrap();
    return Ok(0);
}

pub fn list_job_require_variable(conn: &Connection) -> Vec<JobRequireVariable> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    let mut items = Vec::<JobRequireVariable>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_require_variable_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found job_require_variable {:?}", person.unwrap());
    }
}

pub fn pk_job_require_variable_by_name(
    conn: &Connection,
    job: &i32,
    variable: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable  FROM JOB_REQUIRE_VARIABLE WHERE fk_job = ?1 AND fk_variable = ?2").unwrap();
    let job_require_variable_iter = stmt.query_map(&[job, variable], |row| {
        JobRequireVariable {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable: row.get(2),
        }
    });
    if job_require_variable_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = job_require_variable_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>// Coherence phase
//
// The job of the coherence phase of typechecking is to ensure that each trait
// has at most one implementation for each type. Then we build a mapping from
// each trait in the system to its implementations.

import middle::ty::{get, t, ty_box, ty_uniq, ty_ptr, ty_rptr, ty_enum};
import middle::ty::{ty_class, ty_nil, ty_bot, ty_bool, ty_int, ty_uint};
import middle::ty::{ty_float, ty_str, ty_estr, ty_vec, ty_evec, ty_rec};
import middle::ty::{ty_fn, ty_trait, ty_tup, ty_var, ty_var_integral};
import middle::ty::{ty_param, ty_self, ty_constr, ty_type, ty_opaque_box};
import middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, new_ty_hash};
import middle::ty::{subst};
import middle::typeck::infer::{infer_ctxt, mk_subty, new_infer_ctxt};
import syntax::ast::{crate, def_id, item, item_class, item_const, item_enum};
import syntax::ast::{item_fn, item_foreign_mod, item_impl, item_mac};
import syntax::ast::{item_mod, item_trait, item_ty, local_crate, method};
import syntax::ast::{node_id, region_param, rp_none, rp_self, trait_ref};
import syntax::ast_util::{def_id_of_def, new_def_hash};
import syntax::visit::{default_simple_visitor, default_visitor};
import syntax::visit::{mk_simple_visitor, mk_vt, visit_crate, visit_item};
import syntax::visit::{visit_mod};
import util::ppaux::ty_to_str;

import dvec::{dvec, extensions};
import result::{extensions};
import std::map::{hashmap, int_hash};
import uint::range;

class CoherenceInfo {
    // Contains implementations of methods that are inherent to a type.
    // Methods in these implementations don't need to be exported.
    let inherent_methods: hashmap<t,@dvec<@item>>;

    // Contains implementations of methods associated with a trait. For these,
    // the associated trait must be imported at the call site.
    let extension_methods: hashmap<def_id,@dvec<@item>>;

    new() {
        self.inherent_methods = new_ty_hash();
        self.extension_methods = new_def_hash();
    }
}

class CoherenceChecker {
    let crate_context: @crate_ctxt;
    let inference_context: infer_ctxt;
    let info: @CoherenceInfo;

    // A mapping from implementations to the corresponding base type
    // definition ID.
    let base_type_def_ids: hashmap<node_id,def_id>;

    // A set of implementations in privileged scopes; i.e. those
    // implementations that are defined in the same scope as their base types.
    let privileged_implementations: hashmap<node_id,()>;

    // The set of types that we are currently in the privileged scope of. This
    // is used while we traverse the AST while checking privileged scopes.
    let privileged_types: hashmap<def_id,()>;

    new(crate_context: @crate_ctxt) {
        self.crate_context = crate_context;
        self.inference_context = new_infer_ctxt(crate_context.tcx);
        self.info = @CoherenceInfo();

        self.base_type_def_ids = int_hash();
        self.privileged_implementations = int_hash();
        self.privileged_types = new_def_hash();
    }

    fn check_coherence(crate: @crate) {
        // Check implementations. This populates the tables containing the
        // inherent methods and extension methods.

        visit_crate(*crate, (), mk_simple_visitor(@{
            visit_item: |item| {
                alt item.node {
                    item_impl(_, _, associated_trait, self_type, _) {
                        self.check_implementation(item, associated_trait);
                    }
                    _ {
                        // Nothing to do.
                    }
                };
            }
            with *default_simple_visitor()
        }));

        // Check trait coherence.
        for self.info.extension_methods.each |def_id, items| {
            self.check_implementation_coherence(def_id, items);
        }

        // Check whether traits with base types are in privileged scopes.
        self.check_privileged_scopes(crate);
    }

    fn check_implementation(item: @item,
                            optional_associated_trait: option<@trait_ref>) {

        let self_type = self.crate_context.tcx.tcache.get(local_def(item.id));
        alt optional_associated_trait {
            none {
                alt self.get_base_type(self_type.ty) {
                    none {
                        let session = self.crate_context.tcx.sess;
                        session.span_warn(item.span,
                                          "no base type found for inherent \
                                           implementation; implement a trait \
                                           instead");
                    }
                    some(base_type) {
                        let implementation_list;
                        alt self.info.inherent_methods.find(base_type) {
                            none {
                                implementation_list = @dvec();
                            }
                            some(existing_implementation_list) {
                                implementation_list =
                                    existing_implementation_list;
                            }
                        }

                        implementation_list.push(item);
                    }
                }
            }
            some(associated_trait) {
                let def =
                    self.crate_context.tcx.def_map.get(associated_trait.id);
                let def_id = def_id_of_def(def);

                let implementation_list;
                alt self.info.extension_methods.find(def_id) {
                    none {
                        implementation_list = @dvec();
                    }
                    some(existing_implementation_list) {
                        implementation_list = existing_implementation_list;
                    }
                }

                implementation_list.push(item);
            }
        }

        // Add the implementation to the mapping from implementation to base
        // type def ID, if there is a base type for this implementation.
        alt self.get_base_type_def_id(self_type.ty) {
            none {
                // Nothing to do.
            }
            some(base_type_def_id) {
                self.base_type_def_ids.insert(item.id, base_type_def_id);
            }
        }
    }

    fn get_base_type(original_type: t) -> option<t> {
        alt get(original_type).struct {
            ty_box(base_mutability_and_type) |
            ty_uniq(base_mutability_and_type) |
            ty_ptr(base_mutability_and_type) |
            ty_rptr(_, base_mutability_and_type) {
                self.get_base_type(base_mutability_and_type.ty)
            }

            ty_enum(*) | ty_class(*) {
                some(original_type)
            }

            ty_nil | ty_bot | ty_bool | ty_int(*) | ty_uint(*) | ty_float(*) |
            ty_str | ty_estr(*) | ty_vec(*) | ty_evec(*) | ty_rec(*) |
            ty_fn(*) | ty_trait(*) | ty_tup(*) | ty_var(*) |
            ty_var_integral(*) | ty_param(*) | ty_self | ty_constr(*) |
            ty_type | ty_opaque_box | ty_opaque_closure_ptr(*) |
            ty_unboxed_vec(*) {
                none
            }
        }
    }

    // Returns the def ID of the base type.
    fn get_base_type_def_id(original_type: t) -> option<def_id> {
        alt self.get_base_type(original_type) {
            none {
                ret none;
            }
            some(base_type) {
                alt get(base_type).struct {
                    ty_enum(def_id, _) | ty_class(def_id, _) {
                        ret some(def_id);
                    }
                    _ {
                        fail "get_base_type() returned a type that wasn't an \
                              enum or class";
                    }
                }
            }
        }
    }

    fn check_implementation_coherence(_trait_def_id: def_id,
                                      implementations: @dvec<@item>) {

        // Unify pairs of polytypes.
        for implementations.eachi |i, implementation_a| {
            let polytype_a =
                self.get_self_type_for_implementation(implementation_a);
            for range(i + 1, implementations.len()) |j| {
                let implementation_b = implementations.get_elt(j);
                let polytype_b =
                    self.get_self_type_for_implementation(implementation_b);

                if self.polytypes_unify(polytype_a, polytype_b) {
                    let session = self.crate_context.tcx.sess;
                    session.span_err(implementation_b.span,
                                     "conflicting implementations for a \
                                      trait");
                    session.span_note(implementation_a.span,
                                      "note conflicting implementation here");
                }
            }
        }
    }

    fn polytypes_unify(polytype_a: ty_param_bounds_and_ty,
                       polytype_b: ty_param_bounds_and_ty)
                    -> bool {

        let monotype_a = self.universally_quantify_polytype(polytype_a);
        let monotype_b = self.universally_quantify_polytype(polytype_b);
        ret mk_subty(self.inference_context, monotype_a, monotype_b).is_ok()
         || mk_subty(self.inference_context, monotype_b, monotype_a).is_ok();
    }

    // Converts a polytype to a monotype by replacing all parameters with
    // type variables.
    fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t {
        let self_region;
        alt polytype.rp {
            rp_none {
                self_region = none;
            }
            rp_self {
                self_region = some(self.inference_context.next_region_var())
            }
        };

        let bounds_count = polytype.bounds.len();
        let type_parameters =
            self.inference_context.next_ty_vars(bounds_count);

        let substitutions = {
            self_r: self_region,
            self_ty: none,
            tps: type_parameters
        };

        ret subst(self.crate_context.tcx, substitutions, polytype.ty);
    }

    fn get_self_type_for_implementation(implementation: @item)
                                     -> ty_param_bounds_and_ty {

        alt implementation.node {
            item_impl(*) {
                let def = local_def(implementation.id);
                ret self.crate_context.tcx.tcache.get(def);
            }
            _ {
                self.crate_context.tcx.sess.span_bug(implementation.span,
                                                     "not an implementation");
            }
        }
    }

    // Privileged scope checking

    fn check_privileged_scopes(crate: @crate) {
        visit_crate(*crate, (), mk_vt(@{
            visit_item: |item, _context, visitor| {
                alt item.node {
                    item_mod(module) {
                        // First, gather up all privileged types.
                        let privileged_types =
                            self.gather_privileged_types(module.items);
                        for privileged_types.each |privileged_type| {
                            #debug("(checking privileged scopes) entering \
                                    privileged scope of %d:%d",
                                   privileged_type.crate,
                                   privileged_type.node);

                            self.privileged_types.insert(privileged_type, ());
                        }

                        // Then visit the module items.
                        visit_mod(module, item.span, item.id, (), visitor);

                        // Finally, remove privileged types from the map.
                        for privileged_types.each |privileged_type| {
                            self.privileged_types.remove(privileged_type);
                        }
                    }
                    item_impl(_, _, optional_trait_ref, _, _) {
                        alt self.base_type_def_ids.find(item.id) {
                            none {
                                // Nothing to do.
                            }
                            some(base_type_def_id) {
                                // Check to see whether the implementation is
                                // in the scope of its base type.

                                let privileged_types = &self.privileged_types;
                                if privileged_types.
                                        contains_key(base_type_def_id) {

                                    // Record that this implementation is OK.
                                    self.privileged_implementations.insert
                                        (item.id, ());
                                } else {
                                    // This implementation is not in scope of
                                    // its base type. This still might be OK
                                    // if the trait is defined in the same
                                    // crate.

                                    alt optional_trait_ref {
                                        none {
                                            // There is no trait to implement,
                                            // so this is an error.

                                            let session =
                                                self.crate_context.tcx.sess;
                                            session.span_warn(item.span,
                                                              "cannot \
                                                               implement \
                                                               inherent \
                                                               methods for a \
                                                               type outside \
                                                               the scope the \
                                                               type was \
                                                               defined in; \
                                                               define and \
                                                               implement a \
                                                               trait \
                                                               instead");
                                        }
                                        some(trait_ref) {
                                            // This is OK if and only if the
                                            // trait was defined in this
                                            // crate.

                                            let def_map = self.crate_context
                                                .tcx.def_map;
                                            let trait_def =
                                                def_map.get(trait_ref.id);
                                            let trait_id =
                                                def_id_of_def(trait_def);
                                            if trait_id.crate != local_crate {
                                                let session = self
                                                    .crate_context.tcx.sess;
                                                session.span_warn(item.span,
                                                                  "cannot \
                                                                   provide \
                                                                   an \
                                                                   extension \
                                                                   implement\
                                                                      ation \
                                                                   for a \
                                                                   trait not \
                                                                   defined \
                                                                   in this \
                                                                   crate");
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        visit_item(item, (), visitor);
                    }
                    _ {
                        visit_item(item, (), visitor);
                    }
                }
            }
            with *default_visitor()
        }));
    }

    fn gather_privileged_types(items: ~[@item]) -> @dvec<def_id> {
        let results = @dvec();
        for items.each |item| {
            alt item.node {
                item_class(*) | item_enum(*) {
                    results.push(local_def(item.id));
                }

                item_const(*) | item_fn(*) | item_mod(*) |
                item_foreign_mod(*) | item_ty(*) | item_trait(*) |
                item_impl(*) | item_mac(*) {
                    // Nothing to do.
                }
            }
        }

        ret results;
    }
}

fn check_coherence(crate_context: @crate_ctxt, crate: @crate) {
    CoherenceChecker(crate_context).check_coherence(crate);
}

<commit_msg>rustc: Treat existential traits as base types for coherence purposes<commit_after>// Coherence phase
//
// The job of the coherence phase of typechecking is to ensure that each trait
// has at most one implementation for each type. Then we build a mapping from
// each trait in the system to its implementations.

import middle::ty::{get, t, ty_box, ty_uniq, ty_ptr, ty_rptr, ty_enum};
import middle::ty::{ty_class, ty_nil, ty_bot, ty_bool, ty_int, ty_uint};
import middle::ty::{ty_float, ty_str, ty_estr, ty_vec, ty_evec, ty_rec};
import middle::ty::{ty_fn, ty_trait, ty_tup, ty_var, ty_var_integral};
import middle::ty::{ty_param, ty_self, ty_constr, ty_type, ty_opaque_box};
import middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, new_ty_hash};
import middle::ty::{subst};
import middle::typeck::infer::{infer_ctxt, mk_subty, new_infer_ctxt};
import syntax::ast::{crate, def_id, item, item_class, item_const, item_enum};
import syntax::ast::{item_fn, item_foreign_mod, item_impl, item_mac};
import syntax::ast::{item_mod, item_trait, item_ty, local_crate, method};
import syntax::ast::{node_id, region_param, rp_none, rp_self, trait_ref};
import syntax::ast_util::{def_id_of_def, new_def_hash};
import syntax::visit::{default_simple_visitor, default_visitor};
import syntax::visit::{mk_simple_visitor, mk_vt, visit_crate, visit_item};
import syntax::visit::{visit_mod};
import util::ppaux::ty_to_str;

import dvec::{dvec, extensions};
import result::{extensions};
import std::map::{hashmap, int_hash};
import uint::range;

class CoherenceInfo {
    // Contains implementations of methods that are inherent to a type.
    // Methods in these implementations don't need to be exported.
    let inherent_methods: hashmap<t,@dvec<@item>>;

    // Contains implementations of methods associated with a trait. For these,
    // the associated trait must be imported at the call site.
    let extension_methods: hashmap<def_id,@dvec<@item>>;

    new() {
        self.inherent_methods = new_ty_hash();
        self.extension_methods = new_def_hash();
    }
}

class CoherenceChecker {
    let crate_context: @crate_ctxt;
    let inference_context: infer_ctxt;
    let info: @CoherenceInfo;

    // A mapping from implementations to the corresponding base type
    // definition ID.
    let base_type_def_ids: hashmap<node_id,def_id>;

    // A set of implementations in privileged scopes; i.e. those
    // implementations that are defined in the same scope as their base types.
    let privileged_implementations: hashmap<node_id,()>;

    // The set of types that we are currently in the privileged scope of. This
    // is used while we traverse the AST while checking privileged scopes.
    let privileged_types: hashmap<def_id,()>;

    new(crate_context: @crate_ctxt) {
        self.crate_context = crate_context;
        self.inference_context = new_infer_ctxt(crate_context.tcx);
        self.info = @CoherenceInfo();

        self.base_type_def_ids = int_hash();
        self.privileged_implementations = int_hash();
        self.privileged_types = new_def_hash();
    }

    fn check_coherence(crate: @crate) {
        // Check implementations. This populates the tables containing the
        // inherent methods and extension methods.

        visit_crate(*crate, (), mk_simple_visitor(@{
            visit_item: |item| {
                alt item.node {
                    item_impl(_, _, associated_trait, self_type, _) {
                        self.check_implementation(item, associated_trait);
                    }
                    _ {
                        // Nothing to do.
                    }
                };
            }
            with *default_simple_visitor()
        }));

        // Check trait coherence.
        for self.info.extension_methods.each |def_id, items| {
            self.check_implementation_coherence(def_id, items);
        }

        // Check whether traits with base types are in privileged scopes.
        self.check_privileged_scopes(crate);
    }

    fn check_implementation(item: @item,
                            optional_associated_trait: option<@trait_ref>) {

        let self_type = self.crate_context.tcx.tcache.get(local_def(item.id));
        alt optional_associated_trait {
            none {
                alt self.get_base_type(self_type.ty) {
                    none {
                        let session = self.crate_context.tcx.sess;
                        session.span_warn(item.span,
                                          "no base type found for inherent \
                                           implementation; implement a trait \
                                           instead");
                    }
                    some(base_type) {
                        let implementation_list;
                        alt self.info.inherent_methods.find(base_type) {
                            none {
                                implementation_list = @dvec();
                            }
                            some(existing_implementation_list) {
                                implementation_list =
                                    existing_implementation_list;
                            }
                        }

                        implementation_list.push(item);
                    }
                }
            }
            some(associated_trait) {
                let def =
                    self.crate_context.tcx.def_map.get(associated_trait.id);
                let def_id = def_id_of_def(def);

                let implementation_list;
                alt self.info.extension_methods.find(def_id) {
                    none {
                        implementation_list = @dvec();
                    }
                    some(existing_implementation_list) {
                        implementation_list = existing_implementation_list;
                    }
                }

                implementation_list.push(item);
            }
        }

        // Add the implementation to the mapping from implementation to base
        // type def ID, if there is a base type for this implementation.
        alt self.get_base_type_def_id(self_type.ty) {
            none {
                // Nothing to do.
            }
            some(base_type_def_id) {
                self.base_type_def_ids.insert(item.id, base_type_def_id);
            }
        }
    }

    fn get_base_type(original_type: t) -> option<t> {
        alt get(original_type).struct {
            ty_box(base_mutability_and_type) |
            ty_uniq(base_mutability_and_type) |
            ty_ptr(base_mutability_and_type) |
            ty_rptr(_, base_mutability_and_type) {
                self.get_base_type(base_mutability_and_type.ty)
            }

            ty_enum(*) | ty_trait(*) | ty_class(*) {
                some(original_type)
            }

            ty_nil | ty_bot | ty_bool | ty_int(*) | ty_uint(*) | ty_float(*) |
            ty_str | ty_estr(*) | ty_vec(*) | ty_evec(*) | ty_rec(*) |
            ty_fn(*) | ty_tup(*) | ty_var(*) | ty_var_integral(*) |
            ty_param(*) | ty_self | ty_constr(*) | ty_type | ty_opaque_box |
            ty_opaque_closure_ptr(*) | ty_unboxed_vec(*) {
                none
            }
        }
    }

    // Returns the def ID of the base type.
    fn get_base_type_def_id(original_type: t) -> option<def_id> {
        alt self.get_base_type(original_type) {
            none {
                ret none;
            }
            some(base_type) {
                alt get(base_type).struct {
                    ty_enum(def_id, _) |
                    ty_class(def_id, _) |
                    ty_trait(def_id, _) {
                        ret some(def_id);
                    }
                    _ {
                        fail "get_base_type() returned a type that wasn't an \
                              enum, class, or trait";
                    }
                }
            }
        }
    }

    fn check_implementation_coherence(_trait_def_id: def_id,
                                      implementations: @dvec<@item>) {

        // Unify pairs of polytypes.
        for implementations.eachi |i, implementation_a| {
            let polytype_a =
                self.get_self_type_for_implementation(implementation_a);
            for range(i + 1, implementations.len()) |j| {
                let implementation_b = implementations.get_elt(j);
                let polytype_b =
                    self.get_self_type_for_implementation(implementation_b);

                if self.polytypes_unify(polytype_a, polytype_b) {
                    let session = self.crate_context.tcx.sess;
                    session.span_err(implementation_b.span,
                                     "conflicting implementations for a \
                                      trait");
                    session.span_note(implementation_a.span,
                                      "note conflicting implementation here");
                }
            }
        }
    }

    fn polytypes_unify(polytype_a: ty_param_bounds_and_ty,
                       polytype_b: ty_param_bounds_and_ty)
                    -> bool {

        let monotype_a = self.universally_quantify_polytype(polytype_a);
        let monotype_b = self.universally_quantify_polytype(polytype_b);
        ret mk_subty(self.inference_context, monotype_a, monotype_b).is_ok()
         || mk_subty(self.inference_context, monotype_b, monotype_a).is_ok();
    }

    // Converts a polytype to a monotype by replacing all parameters with
    // type variables.
    fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t {
        let self_region;
        alt polytype.rp {
            rp_none {
                self_region = none;
            }
            rp_self {
                self_region = some(self.inference_context.next_region_var())
            }
        };

        let bounds_count = polytype.bounds.len();
        let type_parameters =
            self.inference_context.next_ty_vars(bounds_count);

        let substitutions = {
            self_r: self_region,
            self_ty: none,
            tps: type_parameters
        };

        ret subst(self.crate_context.tcx, substitutions, polytype.ty);
    }

    fn get_self_type_for_implementation(implementation: @item)
                                     -> ty_param_bounds_and_ty {

        alt implementation.node {
            item_impl(*) {
                let def = local_def(implementation.id);
                ret self.crate_context.tcx.tcache.get(def);
            }
            _ {
                self.crate_context.tcx.sess.span_bug(implementation.span,
                                                     "not an implementation");
            }
        }
    }

    // Privileged scope checking

    fn check_privileged_scopes(crate: @crate) {
        visit_crate(*crate, (), mk_vt(@{
            visit_item: |item, _context, visitor| {
                alt item.node {
                    item_mod(module) {
                        // First, gather up all privileged types.
                        let privileged_types =
                            self.gather_privileged_types(module.items);
                        for privileged_types.each |privileged_type| {
                            #debug("(checking privileged scopes) entering \
                                    privileged scope of %d:%d",
                                   privileged_type.crate,
                                   privileged_type.node);

                            self.privileged_types.insert(privileged_type, ());
                        }

                        // Then visit the module items.
                        visit_mod(module, item.span, item.id, (), visitor);

                        // Finally, remove privileged types from the map.
                        for privileged_types.each |privileged_type| {
                            self.privileged_types.remove(privileged_type);
                        }
                    }
                    item_impl(_, _, optional_trait_ref, _, _) {
                        alt self.base_type_def_ids.find(item.id) {
                            none {
                                // Nothing to do.
                            }
                            some(base_type_def_id) {
                                // Check to see whether the implementation is
                                // in the scope of its base type.

                                let privileged_types = &self.privileged_types;
                                if privileged_types.
                                        contains_key(base_type_def_id) {

                                    // Record that this implementation is OK.
                                    self.privileged_implementations.insert
                                        (item.id, ());
                                } else {
                                    // This implementation is not in scope of
                                    // its base type. This still might be OK
                                    // if the trait is defined in the same
                                    // crate.

                                    alt optional_trait_ref {
                                        none {
                                            // There is no trait to implement,
                                            // so this is an error.

                                            let session =
                                                self.crate_context.tcx.sess;
                                            session.span_warn(item.span,
                                                              "cannot \
                                                               implement \
                                                               inherent \
                                                               methods for a \
                                                               type outside \
                                                               the scope the \
                                                               type was \
                                                               defined in; \
                                                               define and \
                                                               implement a \
                                                               trait \
                                                               instead");
                                        }
                                        some(trait_ref) {
                                            // This is OK if and only if the
                                            // trait was defined in this
                                            // crate.

                                            let def_map = self.crate_context
                                                .tcx.def_map;
                                            let trait_def =
                                                def_map.get(trait_ref.id);
                                            let trait_id =
                                                def_id_of_def(trait_def);
                                            if trait_id.crate != local_crate {
                                                let session = self
                                                    .crate_context.tcx.sess;
                                                session.span_warn(item.span,
                                                                  "cannot \
                                                                   provide \
                                                                   an \
                                                                   extension \
                                                                   implement\
                                                                      ation \
                                                                   for a \
                                                                   trait not \
                                                                   defined \
                                                                   in this \
                                                                   crate");
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        visit_item(item, (), visitor);
                    }
                    _ {
                        visit_item(item, (), visitor);
                    }
                }
            }
            with *default_visitor()
        }));
    }

    fn gather_privileged_types(items: ~[@item]) -> @dvec<def_id> {
        let results = @dvec();
        for items.each |item| {
            alt item.node {
                item_class(*) | item_enum(*) | item_trait(*) {
                    results.push(local_def(item.id));
                }

                item_const(*) | item_fn(*) | item_mod(*) |
                item_foreign_mod(*) | item_ty(*) | item_impl(*) |
                item_mac(*) {
                    // Nothing to do.
                }
            }
        }

        ret results;
    }
}

fn check_coherence(crate_context: @crate_ctxt, crate: @crate) {
    CoherenceChecker(crate_context).check_coherence(crate);
}

<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
    "".chars().fold(|_, _| (), ());
    //~^ ERROR cannot determine a type for this expression: unconstrained type
}
<commit_msg>fix test<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
    "".chars().fold(|_, _| (), ()); //~ ERROR is not implemented for the type `()`
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::io::prelude::*;
use std::process::{Command, Stdio};

static PANGRAM: &'static str =
"the quick brown fox jumped over the lazy dog\n";

fn main() {
    // Spawn the `wc` command
    let process = match Command::new("wc")
                                .stdin(Stdio::piped())
                                .stdout(Stdio::piped())
                                .spawn() {
        Err(why) => panic!("couldn't spawn wc: {}", Error::description(&why)),
        Ok(process) => process,
    };

    {
        // Write a string to the stdin of `wc`
        match process.stdin.unwrap().write_all(PANGRAM.as_bytes()) {
            Err(why) => panic!("couldn't write to wc stdin: {}",
                               Error::description(&why)),
            Ok(_) => println!("sent pangram to wc"),
        }

        // `stdin` gets `drop`ed here, and the pipe is closed
        // This is very important, otherwise `wc` wouldn't start processing the
        // input we just sent
    }

    // The `stdout` field also has type `Option<PipeStream>`
    // the `as_mut` method will return a mutable reference to the value
    // wrapped in a `Some` variant
    let mut s = String::new();
    match process.stdout.unwrap().read_to_string(&mut s) {
        Err(why) => panic!("couldn't read wc stdout: {}",
                           Error::description(&why)),
        Ok(_) => print!("wc responded with:\n{}", s),
    }
}
<commit_msg>std_misc/process/pipe: Update comments to match current API.<commit_after>use std::error::Error;
use std::io::prelude::*;
use std::process::{Command, Stdio};

static PANGRAM: &'static str =
"the quick brown fox jumped over the lazy dog\n";

fn main() {
    // Spawn the `wc` command
    let process = match Command::new("wc")
                                .stdin(Stdio::piped())
                                .stdout(Stdio::piped())
                                .spawn() {
        Err(why) => panic!("couldn't spawn wc: {}", Error::description(&why)),
        Ok(process) => process,
    };

    {
        // Write a string to the stdin of `wc`.
        // stdin has type `Option<ChildStdin>`, but since we know this instance
        // must have one, we can directly `unwrap` it.
        match process.stdin.unwrap().write_all(PANGRAM.as_bytes()) {
            Err(why) => panic!("couldn't write to wc stdin: {}",
                               Error::description(&why)),
            Ok(_) => println!("sent pangram to wc"),
        }

        // `stdin` gets `drop`ed here, and the pipe is closed
        // This is very important, otherwise `wc` wouldn't start processing the
        // input we just sent
    }

    // The `stdout` field also has type `Option<ChildStdout>` so must be unwrapped.
    let mut s = String::new();
    match process.stdout.unwrap().read_to_string(&mut s) {
        Err(why) => panic!("couldn't read wc stdout: {}",
                           Error::description(&why)),
        Ok(_) => print!("wc responded with:\n{}", s),
    }
}
<|endoftext|>