<commit_before>#include "lpg_check.h"
#include "lpg_for.h"
#include "lpg_assert.h"
#include "lpg_allocate.h"
#include "lpg_value.h"
#include "lpg_instruction.h"
#include "lpg_structure_member.h"
#include "lpg_string_literal.h"
#include "lpg_interprete.h"
#include <string.h>

static void add_instruction(instruction_sequence *to, instruction const added)
{
    to->elements =
        reallocate_array(to->elements, (to->length + 1), sizeof(*to->elements));
    to->elements[to->length] = added;
    ++(to->length);
}

struct function_checking_state;

typedef struct evaluate_expression_result
{
    bool has_value;
    register_id where;
    type type_;
    optional_value compile_time_value;
} evaluate_expression_result;

static evaluate_expression_result
evaluate_expression_result_create(register_id const where, type const type_,
                                  optional_value compile_time_value)
{
    evaluate_expression_result result = {
        true, where, type_, compile_time_value};
    return result;
}

static evaluate_expression_result const evaluate_expression_result_empty = {
    false,
    0,
    {type_kind_type, {NULL}},
    {false, {value_kind_integer, {{0, 0}}}}};

typedef struct local_variable
{
    unicode_string name;
    type type_;
    optional_value compile_time_value;
    register_id where;
} local_variable;

static local_variable local_variable_create(unicode_string name,
                                            type const type_,
                                            optional_value compile_time_value,
                                            register_id where)
{
    local_variable result = {name, type_, compile_time_value, where};
    return result;
}

static void local_variable_free(local_variable const *const value)
{
    unicode_string_free(&value->name);
}

typedef struct local_variable_container
{
    local_variable *elements;
    size_t count;
} local_variable_container;

static void add_local_variable(local_variable_container *to,
                               local_variable variable)
{
    to->elements =
        reallocate_array(to->elements, to->count + 1, sizeof(*to->elements));
    to->elements[to->count] = variable;
    ++to->count;
}

static bool local_variable_name_exists(local_variable_container const variables,
                                       unicode_view const name)
{
    LPG_FOR(size_t, i, variables.count)
    {
        if (unicode_view_equals(
                unicode_view_from_string(variables.elements[i].name), name))
        {
            return true;
        }
    }
    return false;
}

typedef struct function_checking_state
{
    register_id used_registers;
    bool is_in_loop;
    structure const *global;
    check_error_handler *on_error;
    local_variable_container local_variables;
    void *user;
    checked_program *program;
} function_checking_state;

static function_checking_state
function_checking_state_create(structure const *global,
                               check_error_handler *on_error, void *user,
                               checked_program *const program)
{
    function_checking_state result = {
        0, false, global, on_error, {NULL, 0}, user, program};
    return result;
}

static register_id allocate_register(function_checking_state *state)
{
    register_id id = state->used_registers;
    ++state->used_registers;
    return id;
}

static evaluate_expression_result
check_sequence(function_checking_state *const state,
               instruction_sequence *const output, sequence const input);

static type get_return_type(type const callee)
{
    switch (callee.kind)
    {
    case type_kind_structure:
        LPG_TO_DO();

    case type_kind_function_pointer:
        return callee.function_pointer_->result;

    case type_kind_unit:
    case type_kind_string_ref:
    case type_kind_enumeration:
        LPG_TO_DO();

    case type_kind_type:
        LPG_TO_DO();

    case type_kind_integer_range:
        LPG_TO_DO();

    case type_kind_inferred:
        LPG_TO_DO();
    }
    UNREACHABLE();
}

typedef struct type_inference
{
    optional_value *values;
    size_t count;
} type_inference;

static void type_inference_free(type_inference const value)
{
    deallocate(value.values);
}

bool is_implicitly_convertible(type const flat_from,
                                      type const flat_into)
{
    if (flat_from.kind != flat_into.kind)
    {
        return false;
    }
    switch (flat_from.kind)
    {
    case type_kind_type:
    case type_kind_unit:
    case type_kind_string_ref:
        return true;

    case type_kind_structure:
        LPG_TO_DO();

    case type_kind_function_pointer:
        LPG_TO_DO(); // todo: Is not easy

    case type_kind_enumeration:
        return flat_from.enum_ == flat_into.enum_;

    case type_kind_integer_range:
        return integer_less_or_equals(flat_into.integer_range_.minimum, flat_from.integer_range_.minimum) &&
               integer_less_or_equals(flat_from.integer_range_.maximum, flat_into.integer_range_.maximum);
<commit_msg>Implemented the function pointer implictly casting<commit_after>#include "lpg_check.h"
#include "lpg_for.h"
#include "lpg_assert.h"
#include "lpg_allocate.h"
#include "lpg_value.h"
#include "lpg_instruction.h"
#include "lpg_structure_member.h"
#include "lpg_string_literal.h"
#include "lpg_interprete.h"
#include <string.h>

static void add_instruction(instruction_sequence *to, instruction const added)
{
    to->elements =
        reallocate_array(to->elements, (to->length + 1), sizeof(*to->elements));
    to->elements[to->length] = added;
    ++(to->length);
}

struct function_checking_state;

typedef struct evaluate_expression_result
{
    bool has_value;
    register_id where;
    type type_;
    optional_value compile_time_value;
} evaluate_expression_result;

static evaluate_expression_result
evaluate_expression_result_create(register_id const where, type const type_,
                                  optional_value compile_time_value)
{
    evaluate_expression_result result = {
        true, where, type_, compile_time_value};
    return result;
}

static evaluate_expression_result const evaluate_expression_result_empty = {
    false,
    0,
    {type_kind_type, {NULL}},
    {false, {value_kind_integer, {{0, 0}}}}};

typedef struct local_variable
{
    unicode_string name;
    type type_;
    optional_value compile_time_value;
    register_id where;
} local_variable;

static local_variable local_variable_create(unicode_string name,
                                            type const type_,
                                            optional_value compile_time_value,
                                            register_id where)
{
    local_variable result = {name, type_, compile_time_value, where};
    return result;
}

static void local_variable_free(local_variable const *const value)
{
    unicode_string_free(&value->name);
}

typedef struct local_variable_container
{
    local_variable *elements;
    size_t count;
} local_variable_container;

static void add_local_variable(local_variable_container *to,
                               local_variable variable)
{
    to->elements =
        reallocate_array(to->elements, to->count + 1, sizeof(*to->elements));
    to->elements[to->count] = variable;
    ++to->count;
}

static bool local_variable_name_exists(local_variable_container const variables,
                                       unicode_view const name)
{
    LPG_FOR(size_t, i, variables.count)
    {
        if (unicode_view_equals(
                unicode_view_from_string(variables.elements[i].name), name))
        {
            return true;
        }
    }
    return false;
}

typedef struct function_checking_state
{
    register_id used_registers;
    bool is_in_loop;
    structure const *global;
    check_error_handler *on_error;
    local_variable_container local_variables;
    void *user;
    checked_program *program;
} function_checking_state;

static function_checking_state
function_checking_state_create(structure const *global,
                               check_error_handler *on_error, void *user,
                               checked_program *const program)
{
    function_checking_state result = {
        0, false, global, on_error, {NULL, 0}, user, program};
    return result;
}

static register_id allocate_register(function_checking_state *state)
{
    register_id id = state->used_registers;
    ++state->used_registers;
    return id;
}

static evaluate_expression_result
check_sequence(function_checking_state *const state,
               instruction_sequence *const output, sequence const input);

static type get_return_type(type const callee)
{
    switch (callee.kind)
    {
    case type_kind_structure:
        LPG_TO_DO();

    case type_kind_function_pointer:
        return callee.function_pointer_->result;

    case type_kind_unit:
    case type_kind_string_ref:
    case type_kind_enumeration:
        LPG_TO_DO();

    case type_kind_type:
        LPG_TO_DO();

    case type_kind_integer_range:
        LPG_TO_DO();

    case type_kind_inferred:
        LPG_TO_DO();
    }
    UNREACHABLE();
}

typedef struct type_inference
{
    optional_value *values;
    size_t count;
} type_inference;

static void type_inference_free(type_inference const value)
{
    deallocate(value.values);
}

bool is_implicitly_convertible(type const flat_from,
                                      type const flat_into)
{
    if (flat_from.kind != flat_into.kind)
    {
        return false;
    }
    switch (flat_from.kind)
    {
    case type_kind_type:
    case type_kind_unit:
    case type_kind_string_ref:
        return true;

    case type_kind_structure:
        LPG_TO_DO();

    case type_kind_function_pointer:
        if(flat_from.function_pointer_->arity != flat_into.function_pointer_->arity)
            return false;

        for (size_t i = 0; i < flat_from.function_pointer_->arity; ++i) {
            if(!type_equals(flat_from.function_pointer_->arguments[i], flat_into.function_pointer_->arguments[i])){
                return false;
            }
        }
        return flat_from.function_pointer_->result.kind ==
                   flat_into.function_pointer_->result.kind;

    case type_kind_enumeration:
        return flat_from.enum_ == flat_into.enum_;

    case type_kind_integer_range:
        return integer_less_or_equals(flat_into.integer_range_.minimum, flat_from.integer_range_.minimum) &&
               integer_less_or_equals(flat_from.integer_range_.maximum, flat_into.integer_range_.maximum);

{'fraction_non_alphanumeric': 0.08061311382344592, 'fraction_numerical': 0.001419244961680386, 'mean_word_length': 2.9692076605332334, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4188295', 'n_tokens_mistral': 3209, 'n_tokens_neox': 3092, 'n_words': 640}