<commit_before>
#include "soltoken.h"
#include "solfunc.h"
#include "solop.h"
#include "soltypes.h"

static void inline sol_func_substitute_parameters(SolList parameters, SolList arguments, bool evaluate_tokens, bool evaluate_lists);

SolFunction sol_func_create(SolList parameters, SolList statements) {
    return (SolFunction) sol_obj_clone_type((SolObject) Function, &(struct sol_func_raw){
            false,
            (SolList) sol_obj_retain((SolObject) parameters),
            (SolList) sol_obj_retain((SolObject) statements),
            sol_token_pool_snapshot()
        }, sizeof(sol_func));
}

SolObject sol_func_execute(SolFunction func, SolList arguments, SolObject self) {
    bool evaluate_tokens = sol_bool_value_of(sol_obj_get_prop((SolObject) func, "$evaluate-tokens"))->value;
    bool evaluate_lists = sol_bool_value_of(sol_obj_get_prop((SolObject) func, "$evaluate-lists"))->value;
    
    if (func->is_operator) {
        SolList evaluated = (SolList) sol_obj_retain((SolObject) sol_list_create(false));
        SOL_LIST_ITR(arguments) {
            SolObject object = arguments->current->value;
            switch (object->type_id) {
                case TYPE_SOL_TOKEN:
                    if (evaluate_tokens) {
                        SolObject evaluated_object = sol_obj_evaluate(object);
                        sol_list_add_obj(evaluated, evaluated_object);
                        sol_obj_release(evaluated_object);
                    } else {
                        sol_list_add_obj(evaluated, object);
                    }
                    break;
                case TYPE_SOL_LIST:
                    if (evaluate_lists) {
                        SolObject evaluated_object = sol_obj_evaluate(object);
                        sol_list_add_obj(evaluated, evaluated_object);
                        sol_obj_release(evaluated_object);
                    } else {
                        sol_list_add_obj(evaluated, object);
                    }
                    break;
                default: {
                    SolObject evaluated_object = sol_obj_evaluate(object);
                    sol_list_add_obj(evaluated, evaluated_object);
                    sol_obj_release(evaluated_object);
                }
            }
        }
        SolObject result = ((SolOperator) func)->operator_ref(evaluated, self);
        sol_obj_release((SolObject) evaluated);
        return result;
    }
    
    SolList statements = func->statements;
    
    // establish closure scope
    sol_token_pool_push_m(func->closure_scope);
    // create function scope
    sol_token_pool_push();
    
    // create 'self' reference
    sol_token_register("self", self);
    
    // insert 'arguments' reference and perform parameter substitution
    sol_token_register("arguments", (SolObject) arguments);
    sol_func_substitute_parameters(func->parameters, arguments, evaluate_tokens, evaluate_lists);
    
    // execute function statements
    SolObject ans = nil;
    
    SOL_LIST_ITR(statements) {
        sol_obj_release(ans);
        ans = sol_obj_evaluate(statements->current->value);
    }
    
    // destroy function/closure scope
    sol_token_pool_pop();
    func->closure_scope = sol_token_pool_pop_m();
    
    return ans;
}

static void inline sol_func_substitute_parameters(SolList parameters, SolList arguments, bool evaluate_tokens, bool evaluate_lists) {
    arguments->current = arguments->first;
    SOL_LIST_ITR(parameters) {
        SolToken token = (SolToken) parameters->current->value;
        SolObject object = arguments->current ? arguments->current->value : nil;
        switch (object->type_id) {
            case TYPE_SOL_TOKEN:
                if (evaluate_tokens) {
                    SolObject evaluated_object = sol_obj_evaluate(object);
                    sol_token_register(token->identifier, evaluated_object);
                    sol_obj_release(evaluated_object);
                } else {
                    sol_token_register(token->identifier, object);
                }
                break;
            case TYPE_SOL_LIST:
                if (evaluate_lists) {
                    SolObject evaluated_object = sol_obj_evaluate(object);
                    sol_token_register(token->identifier, evaluated_object);
                    sol_obj_release(evaluated_object);
                } else {
                    sol_token_register(token->identifier, object);
                }
                break;
            default: {
                SolObject evaluated_object = sol_obj_evaluate(object);
                sol_token_register(token->identifier, evaluated_object);
                sol_obj_release(evaluated_object);
            }
        }
        if (arguments->current) arguments->current = arguments->current->next;
    }
}
<commit_msg>Correctly evaluate elements of the arguments list variable.<commit_after>
#include "soltoken.h"
#include "solfunc.h"
#include "solop.h"
#include "soltypes.h"

static void inline sol_func_substitute_parameters(SolList parameters, SolList arguments, bool evaluate_tokens, bool evaluate_lists);

SolFunction sol_func_create(SolList parameters, SolList statements) {
    return (SolFunction) sol_obj_clone_type((SolObject) Function, &(struct sol_func_raw){
            false,
            (SolList) sol_obj_retain((SolObject) parameters),
            (SolList) sol_obj_retain((SolObject) statements),
            sol_token_pool_snapshot()
        }, sizeof(sol_func));
}

SolObject sol_func_execute(SolFunction func, SolList arguments, SolObject self) {
    bool evaluate_tokens = sol_bool_value_of(sol_obj_get_prop((SolObject) func, "$evaluate-tokens"))->value;
    bool evaluate_lists = sol_bool_value_of(sol_obj_get_prop((SolObject) func, "$evaluate-lists"))->value;
    
    if (func->is_operator) {
        SolList evaluated = (SolList) sol_obj_retain((SolObject) sol_list_create(false));
        SOL_LIST_ITR(arguments) {
            SolObject object = arguments->current->value;
            switch (object->type_id) {
                case TYPE_SOL_TOKEN:
                    if (evaluate_tokens) {
                        SolObject evaluated_object = sol_obj_evaluate(object);
                        sol_list_add_obj(evaluated, evaluated_object);
                        sol_obj_release(evaluated_object);
                    } else {
                        sol_list_add_obj(evaluated, object);
                    }
                    break;
                case TYPE_SOL_LIST:
                    if (evaluate_lists) {
                        SolObject evaluated_object = sol_obj_evaluate(object);
                        sol_list_add_obj(evaluated, evaluated_object);
                        sol_obj_release(evaluated_object);
                    } else {
                        sol_list_add_obj(evaluated, object);
                    }
                    break;
                default: {
                    SolObject evaluated_object = sol_obj_evaluate(object);
                    sol_list_add_obj(evaluated, evaluated_object);
                    sol_obj_release(evaluated_object);
                }
            }
        }
        SolObject result = ((SolOperator) func)->operator_ref(evaluated, self);
        sol_obj_release((SolObject) evaluated);
        return result;
    }
    
    SolList statements = func->statements;
    
    // establish closure scope
    sol_token_pool_push_m(func->closure_scope);
    // create function scope
    sol_token_pool_push();
    
    // create 'self' reference
    sol_token_register("self", self);
    
    // insert 'arguments' reference and perform parameter substitution
    sol_func_substitute_parameters(func->parameters, arguments, evaluate_tokens, evaluate_lists);
    
    // execute function statements
    SolObject ans = nil;
    
    SOL_LIST_ITR(statements) {
        sol_obj_release(ans);
        ans = sol_obj_evaluate(statements->current->value);
    }
    
    // destroy function/closure scope
    sol_token_pool_pop();
    func->closure_scope = sol_token_pool_pop_m();
    
    return ans;
}

static void inline sol_func_substitute_parameters(SolList parameters, SolList arguments, bool evaluate_tokens, bool evaluate_lists) {
    // evaluate arguments
    SolList evaluated = sol_list_create(false);
    sol_token_register("arguments", (SolObject) evaluated);
    SOL_LIST_ITR(arguments) {
        SolObject object = arguments->current->value;
        switch (object->type_id) {
            case TYPE_SOL_TOKEN:
                if (evaluate_tokens) {
                    SolObject evaluated_object = sol_obj_evaluate(object);
                    sol_list_add_obj(evaluated, evaluated_object);
                    sol_obj_release(evaluated_object);
                } else {
                    sol_list_add_obj(evaluated, object);
                }
                break;
            case TYPE_SOL_LIST:
                if (evaluate_lists) {
                    SolObject evaluated_object = sol_obj_evaluate(object);
                    sol_list_add_obj(evaluated, evaluated_object);
                    sol_obj_release(evaluated_object);
                } else {
                    sol_list_add_obj(evaluated, object);
                }
                break;
            default: {
                SolObject evaluated_object = sol_obj_evaluate(object);
                sol_list_add_obj(evaluated, object);
                sol_obj_release(evaluated_object);
            }
        }
    }
    
    // register parameters
    evaluated->current = evaluated->first;
    SOL_LIST_ITR(parameters) {
        SolToken token = (SolToken) parameters->current->value;
        SolObject object = evaluated->current ? evaluated->current->value : nil;
        sol_token_register(token->identifier, object);
        if (evaluated->current) evaluated->current = evaluated->current->next;
    }
}

{'fraction_non_alphanumeric': 0.08423500859540904, 'fraction_numerical': 0.0, 'mean_word_length': 2.118889940081993, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 61, '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': '1810015', 'n_tokens_mistral': 2728, 'n_tokens_neox': 2558, 'n_words': 472}