<commit_before>use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use rand::Rng;

use runtime::{Expect, Flow, Runtime, Side};
use ast;
use prelude::{ArgConstraint, PreludeFunction};

use Variable;
use Module;

pub fn standard(f: &mut HashMap<Arc<String>, PreludeFunction>) {
    f.insert(Arc::new("println".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: false
    });
    f.insert(Arc::new("print".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: false
    });
    f.insert(Arc::new("clone".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: false
    });
    f.insert(Arc::new("debug".into()), PreludeFunction {
        arg_constraints: vec![],
        returns: false
    });
    f.insert(Arc::new("backtrace".into()), PreludeFunction {
        arg_constraints: vec![],
        returns: false
    });
    f.insert(Arc::new("sleep".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: false
    });
    f.insert(Arc::new("round".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("random".into()), PreludeFunction {
        arg_constraints: vec![],
        returns: true
    });
    f.insert(Arc::new("read_number".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("read_line".into()), PreludeFunction {
        arg_constraints: vec![],
        returns: true
    });
    f.insert(Arc::new("len".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("push".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default, ArgConstraint::Arg(0)],
        returns: false
    });
    f.insert(Arc::new("trim_right".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("to_string".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("typeof".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("sqrt".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("sin".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("asin".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("cos".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("acos".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("tan".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("atan".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("exp".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("ln".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("log2".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("log10".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("load".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("load_source_imports".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default; 2],
        returns: true
    });
    f.insert(Arc::new("call".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default; 3],
        returns: true
    });
    f.insert(Arc::new("functions".into()), PreludeFunction {
        arg_constraints: vec![],
        returns: true
    });
}

fn deep_clone(v: &Variable, stack: &Vec<Variable>) -> Variable {
    use Variable::*;

    match *v {
        F64(_) => v.clone(),
        Return => v.clone(),
        Bool(_) => v.clone(),
        Text(_) => v.clone(),
        Object(ref obj) => {
            let mut res = obj.clone();
            for (_, val) in &mut res {
                *val = deep_clone(val, stack);
            }
            Object(res)
        }
        Array(ref arr) => {
            let mut res = arr.clone();
            for it in &mut res {
                *it = deep_clone(it, stack);
            }
            Array(res)
        }
        Ref(ind) => {
            deep_clone(&stack[ind], stack)
        }
        UnsafeRef(_) => panic!("Unsafe reference can not be cloned"),
        RustObject(_) => v.clone(),
        Option(None) => Variable::Option(None),
        Option(Some(ref v)) => deep_clone(v, stack)
    }
}

fn print_variable(rt: &Runtime, v: &Variable) {
    match *rt.resolve(v) {
        Variable::Text(ref t) => {
            print!("{}", t);
        }
        Variable::F64(x) => {
            print!("{}", x);
        }
        Variable::Bool(x) => {
            print!("{}", x);
        }
        Variable::Ref(ind) => {
            print_variable(rt, &rt.stack[ind]);
        }
        Variable::Object(ref obj) => {
            print!("{{");
            let n = obj.len();
            for (i, (k, v)) in obj.iter().enumerate() {
                print!("{}: ", k);
                print_variable(rt, v);
                if i + 1 < n {
                    print!(", ");
                }
            }
            print!("}}");
        }
        Variable::Array(ref arr) => {
            print!("[");
            let n = arr.len();
            for (i, v) in arr.iter().enumerate() {
                print_variable(rt, v);
                if i + 1 < n {
                    print!(", ");
                }
            }
            print!("]");
        }
        Variable::Option(ref opt) => {
            match opt {
                &None => {
                    print!("none()")
                }
                &Some(ref v) => {
                    print!("some(");
                    print_variable(rt, v);
                    print!(")");
                }
            }
        }
        ref x => panic!("Could not print out `{:?}`", x)
    }
}

pub fn call_standard(
    rt: &mut Runtime,
    call: &ast::Call,
    module: &Module
) -> Result<(Expect, Flow), String> {
    let st = rt.stack.len();
    let lc = rt.local_stack.len();
    for arg in &call.args {
        match try!(rt.expression(arg, Side::Right, module)) {
            (x, Flow::Return) => { return Ok((x, Flow::Return)); }
            (Expect::Something, Flow::Continue) => {}
            _ => return Err(module.error(arg.source_range(),
                            "Expected something. \
                            Expression did not return a value."))
        };
    }
    let expect = match &**call.name {
        "clone" => {
            rt.push_fn(call.name.clone(), st + 1, lc);
            let v = rt.stack.pop()
                .expect("There is no value on the stack");
            let v = deep_clone(rt.resolve(&v), &rt.stack);
            rt.stack.push(v);
            rt.pop_fn(call.name.clone());
            Expect::Something
        }
        "println" => {
            rt.push_fn(call.name.clone(), st, lc);
            let x = rt.stack.pop()
                .expect("There is no value on the stack");
            print_variable(rt, &x);
            println!("");
            rt.pop_fn(call.name.clone());
            Expect::Nothing
        }
        "print" => {
            rt.push_fn(call.name.clone(), st, lc);
            let x = rt.stack.pop()
                .expect("There is no value on the stack");
            print_variable(rt, &x);
            rt.pop_fn(call.name.clone());
            Expect::Nothing
        }
        "sqrt" => try!(rt.unary_f64(call, module, |a| a.sqrt())),
        "sin" => try!(rt.unary_f64(call, module, |a| a.sin())),
        "asin" => try!(rt.unary_f64(call, module, |a| a.asin())),
        "cos" => try!(rt.unary_f64(call, module, |a| a.cos())),
        "acos" => try!(rt.unary_f64(call, module, |a| a.acos())),
        "tan" => try!(rt.unary_f64(call, module, |a| a.tan())),
        "atan" => try!(rt.unary_f64(call, module, |a| a.atan())),
        "exp" => try!(rt.unary_f64(call, module, |a| a.exp())),
        "ln" => try!(rt.unary_f64(call, module, |a| a.ln())),
        "log2" => try!(rt.unary_f64(call, module, |a| a.log2())),
        "log10" => try!(rt.unary_f64(call, module, |a| a.log10())),
        "sleep" => {<commit_msg>Escape strings in objects and arrays<commit_after>use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use rand::Rng;
use piston_meta::json;

use runtime::{Expect, Flow, Runtime, Side};
use ast;
use prelude::{ArgConstraint, PreludeFunction};

use Variable;
use Module;

pub fn standard(f: &mut HashMap<Arc<String>, PreludeFunction>) {
    f.insert(Arc::new("println".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: false
    });
    f.insert(Arc::new("print".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: false
    });
    f.insert(Arc::new("clone".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: false
    });
    f.insert(Arc::new("debug".into()), PreludeFunction {
        arg_constraints: vec![],
        returns: false
    });
    f.insert(Arc::new("backtrace".into()), PreludeFunction {
        arg_constraints: vec![],
        returns: false
    });
    f.insert(Arc::new("sleep".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: false
    });
    f.insert(Arc::new("round".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("random".into()), PreludeFunction {
        arg_constraints: vec![],
        returns: true
    });
    f.insert(Arc::new("read_number".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("read_line".into()), PreludeFunction {
        arg_constraints: vec![],
        returns: true
    });
    f.insert(Arc::new("len".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("push".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default, ArgConstraint::Arg(0)],
        returns: false
    });
    f.insert(Arc::new("trim_right".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("to_string".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("typeof".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("sqrt".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("sin".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("asin".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("cos".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("acos".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("tan".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("atan".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("exp".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("ln".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("log2".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("log10".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("load".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default],
        returns: true
    });
    f.insert(Arc::new("load_source_imports".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default; 2],
        returns: true
    });
    f.insert(Arc::new("call".into()), PreludeFunction {
        arg_constraints: vec![ArgConstraint::Default; 3],
        returns: true
    });
    f.insert(Arc::new("functions".into()), PreludeFunction {
        arg_constraints: vec![],
        returns: true
    });
}

fn deep_clone(v: &Variable, stack: &Vec<Variable>) -> Variable {
    use Variable::*;

    match *v {
        F64(_) => v.clone(),
        Return => v.clone(),
        Bool(_) => v.clone(),
        Text(_) => v.clone(),
        Object(ref obj) => {
            let mut res = obj.clone();
            for (_, val) in &mut res {
                *val = deep_clone(val, stack);
            }
            Object(res)
        }
        Array(ref arr) => {
            let mut res = arr.clone();
            for it in &mut res {
                *it = deep_clone(it, stack);
            }
            Array(res)
        }
        Ref(ind) => {
            deep_clone(&stack[ind], stack)
        }
        UnsafeRef(_) => panic!("Unsafe reference can not be cloned"),
        RustObject(_) => v.clone(),
        Option(None) => Variable::Option(None),
        Option(Some(ref v)) => deep_clone(v, stack)
    }
}

enum EscapeString {
    Json,
    None
}

fn print_variable(rt: &Runtime, v: &Variable, escape_string: EscapeString) {
    match *rt.resolve(v) {
        Variable::Text(ref t) => {
            match escape_string {
                EscapeString::Json => {
                    let mut w: Vec<u8> = vec![];
                    json::write_string(&mut w, t).unwrap();
                    print!("{}", String::from_utf8(w).unwrap());
                }
                EscapeString::None => {
                    print!("{}", t)
                }
            }
        }
        Variable::F64(x) => {
            print!("{}", x);
        }
        Variable::Bool(x) => {
            print!("{}", x);
        }
        Variable::Ref(ind) => {
            print_variable(rt, &rt.stack[ind], escape_string);
        }
        Variable::Object(ref obj) => {
            print!("{{");
            let n = obj.len();
            for (i, (k, v)) in obj.iter().enumerate() {
                print!("{}: ", k);
                print_variable(rt, v, EscapeString::Json);
                if i + 1 < n {
                    print!(", ");
                }
            }
            print!("}}");
        }
        Variable::Array(ref arr) => {
            print!("[");
            let n = arr.len();
            for (i, v) in arr.iter().enumerate() {
                print_variable(rt, v, EscapeString::Json);
                if i + 1 < n {
                    print!(", ");
                }
            }
            print!("]");
        }
        Variable::Option(ref opt) => {
            match opt {
                &None => {
                    print!("none()")
                }
                &Some(ref v) => {
                    print!("some(");
                    print_variable(rt, v, EscapeString::Json);
                    print!(")");
                }
            }
        }
        ref x => panic!("Could not print out `{:?}`", x)
    }
}

pub fn call_standard(
    rt: &mut Runtime,
    call: &ast::Call,
    module: &Module
) -> Result<(Expect, Flow), String> {
    let st = rt.stack.len();
    let lc = rt.local_stack.len();
    for arg in &call.args {
        match try!(rt.expression(arg, Side::Right, module)) {
            (x, Flow::Return) => { return Ok((x, Flow::Return)); }
            (Expect::Something, Flow::Continue) => {}
            _ => return Err(module.error(arg.source_range(),
                            "Expected something. \
                            Expression did not return a value."))
        };
    }
    let expect = match &**call.name {
        "clone" => {
            rt.push_fn(call.name.clone(), st + 1, lc);
            let v = rt.stack.pop()
                .expect("There is no value on the stack");
            let v = deep_clone(rt.resolve(&v), &rt.stack);
            rt.stack.push(v);
            rt.pop_fn(call.name.clone());
            Expect::Something
        }
        "println" => {
            rt.push_fn(call.name.clone(), st, lc);
            let x = rt.stack.pop()
                .expect("There is no value on the stack");
            print_variable(rt, &x, EscapeString::None);
            println!("");
            rt.pop_fn(call.name.clone());
            Expect::Nothing
        }
        "print" => {
            rt.push_fn(call.name.clone(), st, lc);
            let x = rt.stack.pop()
                .expect("There is no value on the stack");
            print_variable(rt, &x, EscapeString::None);
            rt.pop_fn(call.name.clone());
            Expect::Nothing
        }
        "sqrt" => try!(rt.unary_f64(call, module, |a| a.sqrt())),
        "sin" => try!(rt.unary_f64(call, module, |a| a.sin())),
        "asin" => try!(rt.unary_f64(call, module, |a| a.asin())),
        "cos" => try!(rt.unary_f64(call, module, |a| a.cos())),
        "acos" => try!(rt.unary_f64(call, module, |a| a.acos())),
        "tan" => try!(rt.unary_f64(call, module, |a| a.tan())),
        "atan" => try!(rt.unary_f64(call, module, |a| a.atan())),
        "exp" => try!(rt.unary_f64(call, module, |a| a.exp())),
        "ln" => try!(rt.unary_f64(call, module, |a| a.ln())),
        "log2" => try!(rt.unary_f64(call, module, |a| a.log2())),
        "log10" => try!(rt.unary_f64(call, module, |a| a.log10())),
        "sleep" => {
{'fraction_non_alphanumeric': 0.1750832848606631, 'fraction_numerical': 0.00444185923536566, 'mean_word_length': 2.0503225806451613, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 96, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5898848', 'n_tokens_mistral': 5855, 'n_tokens_neox': 5772, 'n_words': 1071}