<commit_before>#include "rdb_protocol/func.hpp"

#include "rdb_protocol/env.hpp"
#include "rdb_protocol/pb_utils.hpp"
#include "rdb_protocol/ql2.pb.h"

#pragma GCC diagnostic ignored "-Wshadow"

namespace ql {

func_t::func_t(env_t *env, js::id_t id, term_t *parent)
    : pb_rcheckable_t(parent), body(0), source(0),
      js_parent(parent), js_env(env), js_id(id) { }

func_t::func_t(env_t *env, const Term *_source)
    : pb_rcheckable_t(_source), body(0), source(_source),
      js_parent(0), js_env(0), js_id(js::INVALID_ID) {
    const Term *t = _source;
    r_sanity_check(t->type() == Term_TermType_FUNC);
    rcheck(t->optargs_size() == 0, "FUNC takes no optional arguments.");
    rcheck(t->args_size() == 2, strprintf("Func takes exactly two arguments (got %d)",
                                          t->args_size()));

    std::vector<int> args;
    const Term *vars = &t->args(0);
    if (vars->type() == Term_TermType_DATUM) {
        const Datum *d = &vars->datum();
        rcheck(d->type() == Datum_DatumType_R_ARRAY,
               "CLIENT ERROR: FUNC variables must be a literal *array* of numbers.");
        for (int i = 0; i < d->r_array_size(); ++i) {
            const Datum *dnum = &d->r_array(i);
            rcheck(dnum->type() == Datum_DatumType_R_NUM,
                   "CLIENT ERROR: FUNC variables must be a literal array of *numbers*.");
            args.push_back(dnum->r_num());
        }
    } else if (vars->type() == Term_TermType_MAKE_ARRAY) {
        for (int i = 0; i < vars->args_size(); ++i) {
            const Term *arg = &vars->args(i);
            rcheck(arg->type() == Term_TermType_DATUM,
                   "CLIENT ERROR: FUNC variables must be a *literal* array of numbers.");
            const Datum *dnum = &arg->datum();
            rcheck(dnum->type() == Datum_DatumType_R_NUM,
                   "CLIENT ERROR: FUNC variables must be a literal array of *numbers*.");
            args.push_back(dnum->r_num());
        }
    } else {
        rfail("CLIENT ERROR: FUNC variables must be a *literal array of numbers*.");
    }

    guarantee(argptrs.size() == 0);
    argptrs.reserve(args.size()); // NECESSARY FOR POINTERS TO REMAIN VALID
    for (size_t i = 0; i < args.size(); ++i) {
        argptrs.push_back(0);
        env->push_var(args[i], &argptrs[i]);
    }
    if (args.size() == 1 && env_t::var_allows_implicit(args[0])) {
        env->push_implicit(&argptrs[0]);
    }

    if (args.size()) guarantee(env->top_var(args[0], this) == &argptrs[0]);

    const Term *body_source = &t->args(1);
    body = env->new_term(body_source);

    for (size_t i = 0; i < args.size(); ++i) {
        env->pop_var(args[i]);
    }
    if (args.size() == 1 && env_t::var_allows_implicit(args[0])) {
        env->pop_implicit();
    }

    env->dump_scope(&scope);
}

val_t *func_t::call(const std::vector<const datum_t *> &args) {
    try {
        if (js_parent != 0) {
            r_sanity_check(!body && !source && js_env);
            // Convert datum args to cJSON args for the JS runner
            std::vector<boost::shared_ptr<scoped_cJSON_t> > json_args;
            for (auto arg_iter = args.begin(); arg_it != args.end(); ++arg_iter) {
                json_args.push_back((*arg_iter)->as_json());
            }

            boost::shared_ptr<js::runner_t> js = js_env->get_js_runner();
            js::js_result_t result = js->call(js_id, json_args);

            return boost::apply_visitor(js_result_visitor_t(js_env, js_parent), result);
        } else {
            r_sanity_check(body && source && !js_env);
            rcheck(args.size() == argptrs.size() || argptrs.size() == 0,
                   strprintf("Expected %zu argument(s) but found %zu.",
                             argptrs.size(), args.size()));
            for (size_t i = 0; i < argptrs.size(); ++i) {
                r_sanity_check(args[i]);
                argptrs[i] = args[i];
            }
            return body->eval(false);
            //                ^^^^^ don't use cached value
        }
    } catch (const datum_exc_t &e) {
        rfail("%s", e.what());
        unreachable();
    }
}

val_t *func_t::call() {
    std::vector<const datum_t *> args;
    return call(args);
}

val_t *func_t::call(const datum_t *arg) {<commit_msg>Replaced arg_it with arg_iter, silly.<commit_after>#include "rdb_protocol/func.hpp"

#include "rdb_protocol/env.hpp"
#include "rdb_protocol/pb_utils.hpp"
#include "rdb_protocol/ql2.pb.h"

#pragma GCC diagnostic ignored "-Wshadow"

namespace ql {

func_t::func_t(env_t *env, js::id_t id, term_t *parent)
    : pb_rcheckable_t(parent), body(0), source(0),
      js_parent(parent), js_env(env), js_id(id) { }

func_t::func_t(env_t *env, const Term *_source)
    : pb_rcheckable_t(_source), body(0), source(_source),
      js_parent(0), js_env(0), js_id(js::INVALID_ID) {
    const Term *t = _source;
    r_sanity_check(t->type() == Term_TermType_FUNC);
    rcheck(t->optargs_size() == 0, "FUNC takes no optional arguments.");
    rcheck(t->args_size() == 2, strprintf("Func takes exactly two arguments (got %d)",
                                          t->args_size()));

    std::vector<int> args;
    const Term *vars = &t->args(0);
    if (vars->type() == Term_TermType_DATUM) {
        const Datum *d = &vars->datum();
        rcheck(d->type() == Datum_DatumType_R_ARRAY,
               "CLIENT ERROR: FUNC variables must be a literal *array* of numbers.");
        for (int i = 0; i < d->r_array_size(); ++i) {
            const Datum *dnum = &d->r_array(i);
            rcheck(dnum->type() == Datum_DatumType_R_NUM,
                   "CLIENT ERROR: FUNC variables must be a literal array of *numbers*.");
            args.push_back(dnum->r_num());
        }
    } else if (vars->type() == Term_TermType_MAKE_ARRAY) {
        for (int i = 0; i < vars->args_size(); ++i) {
            const Term *arg = &vars->args(i);
            rcheck(arg->type() == Term_TermType_DATUM,
                   "CLIENT ERROR: FUNC variables must be a *literal* array of numbers.");
            const Datum *dnum = &arg->datum();
            rcheck(dnum->type() == Datum_DatumType_R_NUM,
                   "CLIENT ERROR: FUNC variables must be a literal array of *numbers*.");
            args.push_back(dnum->r_num());
        }
    } else {
        rfail("CLIENT ERROR: FUNC variables must be a *literal array of numbers*.");
    }

    guarantee(argptrs.size() == 0);
    argptrs.reserve(args.size()); // NECESSARY FOR POINTERS TO REMAIN VALID
    for (size_t i = 0; i < args.size(); ++i) {
        argptrs.push_back(0);
        env->push_var(args[i], &argptrs[i]);
    }
    if (args.size() == 1 && env_t::var_allows_implicit(args[0])) {
        env->push_implicit(&argptrs[0]);
    }

    if (args.size()) guarantee(env->top_var(args[0], this) == &argptrs[0]);

    const Term *body_source = &t->args(1);
    body = env->new_term(body_source);

    for (size_t i = 0; i < args.size(); ++i) {
        env->pop_var(args[i]);
    }
    if (args.size() == 1 && env_t::var_allows_implicit(args[0])) {
        env->pop_implicit();
    }

    env->dump_scope(&scope);
}

val_t *func_t::call(const std::vector<const datum_t *> &args) {
    try {
        if (js_parent != 0) {
            r_sanity_check(!body && !source && js_env);
            // Convert datum args to cJSON args for the JS runner
            std::vector<boost::shared_ptr<scoped_cJSON_t> > json_args;
            for (auto arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) {
                json_args.push_back((*arg_iter)->as_json());
            }

            boost::shared_ptr<js::runner_t> js = js_env->get_js_runner();
            js::js_result_t result = js->call(js_id, json_args);

            return boost::apply_visitor(js_result_visitor_t(js_env, js_parent), result);
        } else {
            r_sanity_check(body && source && !js_env);
            rcheck(args.size() == argptrs.size() || argptrs.size() == 0,
                   strprintf("Expected %zu argument(s) but found %zu.",
                             argptrs.size(), args.size()));
            for (size_t i = 0; i < argptrs.size(); ++i) {
                r_sanity_check(args[i]);
                argptrs[i] = args[i];
            }
            return body->eval(false);
            //                ^^^^^ don't use cached value
        }
    } catch (const datum_exc_t &e) {
        rfail("%s", e.what());
        unreachable();
    }
}

val_t *func_t::call() {
    std::vector<const datum_t *> args;
    return call(args);
}

val_t *func_t::call(const datum_t *arg) {
{'fraction_non_alphanumeric': 0.16185374941779226, 'fraction_numerical': 0.006054960409874243, 'mean_word_length': 2.4056304520222045, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3274616', 'n_tokens_mistral': 3012, 'n_tokens_neox': 2958, 'n_words': 628}