<commit_before>#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>

#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "map.h"
#include "runtime.h"
#include "bc.h"

/******************************************************************************/
/* native functions                                                           */

// mp_obj_fun_native_t defined in obj.h

void check_nargs(mp_obj_fun_native_t *self, int n_args, int n_kw) {
    if (n_kw && !self->is_kw) {
        nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError,
                                          "function does not take keyword arguments"));
    }

    if (self->n_args_min == self->n_args_max) {
        if (n_args != self->n_args_min) {
            nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError,
                                                     "function takes %d positional arguments but %d were given",
                                                     (const char*)(machine_int_t)self->n_args_min,
                                                     (const char*)(machine_int_t)n_args));
        }
    } else {
        if (n_args < self->n_args_min) {
            nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError,
                                                    "<fun name>() missing %d required positional arguments: <list of names of params>",
                                                    (const char*)(machine_int_t)(self->n_args_min - n_args)));
        } else if (n_args > self->n_args_max) {
            nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError,
                                                     "<fun name> expected at most %d arguments, got %d",
                                                     (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args));
        }
    }
}

mp_obj_t fun_native_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
    assert(MP_OBJ_IS_TYPE(self_in, &fun_native_type));
    mp_obj_fun_native_t *self = self_in;

    // check number of arguments
    check_nargs(self, n_args, n_kw);

    if (self->is_kw) {
        // function allows keywords

        // TODO if n_kw==0 then don't allocate any memory for map (either pass NULL or allocate it on the heap)
        mp_map_t *kw_args = mp_map_new(n_kw);
        for (int i = 0; i < 2 * n_kw; i += 2) {
            mp_map_lookup(kw_args, args[n_args + i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = args[n_args + i + 1];
        }
        mp_obj_t res = ((mp_fun_kw_t)self->fun)(n_args, args, kw_args);
        // TODO clean up kw_args

        return res;

    } else if (self->n_args_min == self->n_args_max) {
        // function requires a fixed number of arguments

        // dispatch function call
        switch (self->n_args_min) {
            case 0:
                return ((mp_fun_0_t)self->fun)();
<commit_msg>Functions of fixed number of args are special-cased only for 3 or less args.<commit_after>#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>

#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
#include "map.h"
#include "runtime.h"
#include "bc.h"

/******************************************************************************/
/* native functions                                                           */

// mp_obj_fun_native_t defined in obj.h

void check_nargs(mp_obj_fun_native_t *self, int n_args, int n_kw) {
    if (n_kw && !self->is_kw) {
        nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError,
                                          "function does not take keyword arguments"));
    }

    if (self->n_args_min == self->n_args_max) {
        if (n_args != self->n_args_min) {
            nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError,
                                                     "function takes %d positional arguments but %d were given",
                                                     (const char*)(machine_int_t)self->n_args_min,
                                                     (const char*)(machine_int_t)n_args));
        }
    } else {
        if (n_args < self->n_args_min) {
            nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError,
                                                    "<fun name>() missing %d required positional arguments: <list of names of params>",
                                                    (const char*)(machine_int_t)(self->n_args_min - n_args)));
        } else if (n_args > self->n_args_max) {
            nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError,
                                                     "<fun name> expected at most %d arguments, got %d",
                                                     (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args));
        }
    }
}

mp_obj_t fun_native_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
    assert(MP_OBJ_IS_TYPE(self_in, &fun_native_type));
    mp_obj_fun_native_t *self = self_in;

    // check number of arguments
    check_nargs(self, n_args, n_kw);

    if (self->is_kw) {
        // function allows keywords

        // TODO if n_kw==0 then don't allocate any memory for map (either pass NULL or allocate it on the heap)
        mp_map_t *kw_args = mp_map_new(n_kw);
        for (int i = 0; i < 2 * n_kw; i += 2) {
            mp_map_lookup(kw_args, args[n_args + i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = args[n_args + i + 1];
        }
        mp_obj_t res = ((mp_fun_kw_t)self->fun)(n_args, args, kw_args);
        // TODO clean up kw_args

        return res;

    } else if (self->n_args_min <= 3 && self->n_args_min == self->n_args_max) {
        // function requires a fixed number of arguments

        // dispatch function call
        switch (self->n_args_min) {
            case 0:
                return ((mp_fun_0_t)self->fun)();

{'fraction_non_alphanumeric': 0.1300731869594145, 'fraction_numerical': 0.003659347970725216, 'mean_word_length': 1.8811691423095351, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 52, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3159587', 'n_tokens_mistral': 1901, 'n_tokens_neox': 1844, 'n_words': 413}