// Kyler Olsen
// YREA SLS
// Builtin Functions
// November 2025

#include <stdlib.h>
#include <math.h>

#include "sls/bool.h"
#include "sls/builtin.h"
#include "sls/hash_table.h"
#include "sls/interpreter.h"
#include "sls/lexer.h"
#include "sls/file.h"

Boolean builtin_addition(InterpreterState *interpreter_state);
Boolean builtin_subtraction(InterpreterState *interpreter_state);
Boolean builtin_multiplication(InterpreterState *interpreter_state);
Boolean builtin_division(InterpreterState *interpreter_state);
Boolean builtin_modulus(InterpreterState *interpreter_state);
Boolean builtin_exponential(InterpreterState *interpreter_state);
Boolean builtin_greater_than(InterpreterState *interpreter_state);
Boolean builtin_greater_than_or_equal_to(InterpreterState *interpreter_state);
Boolean builtin_less_than(InterpreterState *interpreter_state);
Boolean builtin_less_than_or_equal_to(InterpreterState *interpreter_state);
Boolean builtin_equal_to(InterpreterState *interpreter_state);
Boolean builtin_not_equal_to(InterpreterState *interpreter_state);
Boolean builtin_abs(InterpreterState *interpreter_state);
Boolean builtin_acos(InterpreterState *interpreter_state);
Boolean builtin_and(InterpreterState *interpreter_state);
Boolean builtin_asin(InterpreterState *interpreter_state);
// Boolean builtin_assert(InterpreterState *interpreter_state);
// Boolean builtin_at(InterpreterState *interpreter_state);
Boolean builtin_atan(InterpreterState *interpreter_state);
Boolean builtin_atan2(InterpreterState *interpreter_state);
Boolean builtin_bitand(InterpreterState *interpreter_state);
Boolean builtin_bitnot(InterpreterState *interpreter_state);
Boolean builtin_bitor(InterpreterState *interpreter_state);
Boolean builtin_bitxor(InterpreterState *interpreter_state);
Boolean builtin_ceil(InterpreterState *interpreter_state);
// Boolean builtin_concat(InterpreterState *interpreter_state);
Boolean builtin_const(InterpreterState *interpreter_state);
Boolean builtin_cos(InterpreterState *interpreter_state);
Boolean builtin_depth(InterpreterState *interpreter_state);
Boolean builtin_drop(InterpreterState *interpreter_state);
Boolean builtin_dup(InterpreterState *interpreter_state);
// Boolean builtin_each(InterpreterState *interpreter_state);
// Boolean builtin_ends_with(InterpreterState *interpreter_state);
// Boolean builtin_enum(InterpreterState *interpreter_state);
// Boolean builtin_enumerate(InterpreterState *interpreter_state);
Boolean builtin_eval(InterpreterState *interpreter_state);
// Boolean builtin_filter(InterpreterState *interpreter_state);
// Boolean builtin_find(InterpreterState *interpreter_state);
Boolean builtin_floor(InterpreterState *interpreter_state);
// Boolean builtin_fn(InterpreterState *interpreter_state);
// Boolean builtin_foldl(InterpreterState *interpreter_state);
// Boolean builtin_foldr(InterpreterState *interpreter_state);
Boolean builtin_for(InterpreterState *interpreter_state);
// Boolean builtin_format(InterpreterState *interpreter_state);
// Boolean builtin_get(InterpreterState *interpreter_state);
Boolean builtin_if(InterpreterState *interpreter_state);
// Boolean builtin_impl(InterpreterState *interpreter_state);
// Boolean builtin_implements(InterpreterState *interpreter_state);
// Boolean builtin_inher(InterpreterState *interpreter_state);
Boolean builtin_lambda(InterpreterState *interpreter_state);
// Boolean builtin_length(InterpreterState *interpreter_state);
Boolean builtin_ln(InterpreterState *interpreter_state);
Boolean builtin_log(InterpreterState *interpreter_state);
// Boolean builtin_map(InterpreterState *interpreter_state);
// Boolean builtin_match(InterpreterState *interpreter_state);
// Boolean builtin_mean(InterpreterState *interpreter_state);
Boolean builtin_not(InterpreterState *interpreter_state);
Boolean builtin_or(InterpreterState *interpreter_state);
// Boolean builtin_over(InterpreterState *interpreter_state);
Boolean builtin_pick(InterpreterState *interpreter_state);
Boolean builtin_rand(InterpreterState *interpreter_state);
// Boolean builtin_reduce(InterpreterState *interpreter_state);
// Boolean builtin_replace(InterpreterState *interpreter_state);
// Boolean builtin_reverse(InterpreterState *interpreter_state);
Boolean builtin_roll(InterpreterState *interpreter_state);
Boolean builtin_round(InterpreterState *interpreter_state);
Boolean builtin_seed(InterpreterState *interpreter_state);
// Boolean builtin_set(InterpreterState *interpreter_state);
Boolean builtin_shl(InterpreterState *interpreter_state);
Boolean builtin_shr(InterpreterState *interpreter_state);
Boolean builtin_sin(InterpreterState *interpreter_state);
// Boolean builtin_slice(InterpreterState *interpreter_state);
// Boolean builtin_split(InterpreterState *interpreter_state);
Boolean builtin_sqrt(InterpreterState *interpreter_state);
// Boolean builtin_starts_with(InterpreterState *interpreter_state);
// Boolean builtin_struct(InterpreterState *interpreter_state);
// Boolean builtin_substr(InterpreterState *interpreter_state);
// Boolean builtin_sum(InterpreterState *interpreter_state);
Boolean builtin_swap(InterpreterState *interpreter_state);
Boolean builtin_tan(InterpreterState *interpreter_state);
// Boolean builtin_trait(InterpreterState *interpreter_state);
// Boolean builtin_transpose(InterpreterState *interpreter_state);
// Boolean builtin_trim(InterpreterState *interpreter_state);
Boolean builtin_type_of(InterpreterState *interpreter_state);
// Boolean builtin_union(InterpreterState *interpreter_state);
Boolean builtin_while(InterpreterState *interpreter_state);
// Boolean builtin_window(InterpreterState *interpreter_state);
// Boolean builtin_zip(InterpreterState *interpreter_state);

static inline Boolean hash_table_put_funcs(HashTable *ht, SlsStr key, FunctionItem *item) {
    return hash_table_put(ht, key, (void *)item);
}

typedef enum {
    NUMERIC_FLOAT = 1 << 0,
    NUMERIC_SIGNED = 1 << 1,
    NUMERIC_64 = 1 << 2,
    NUMERIC_32 = 1 << 3,
    NUMERIC_16 = 1 << 4,
    NUMERIC_8  = 1 << 5,
} NumericTypes;


Boolean load_builtins(InterpreterState *interpreter_state) {
    FunctionItem *func;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_addition};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("+"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_subtraction};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("-"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_multiplication};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("*"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_division};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("/"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_modulus};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("%"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_exponential};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("^"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_greater_than};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR(">"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_greater_than_or_equal_to};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR(">="), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_less_than};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("<"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_less_than_or_equal_to};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("<="), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_equal_to};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("=="), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_not_equal_to};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("!="), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_abs};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("abs"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_acos};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("acos"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_and};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("acos"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_asin};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("asin"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_atan};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("atan"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_atan2};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("atan2"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_bitand};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("bitand"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_bitnot};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("bitnot"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_bitor};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("bitor"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_bitxor};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("bitxor"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_ceil};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("ceil"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_const};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("const"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_cos};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("cos"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_depth};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("depth"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_drop};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("drop"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_dup};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("dup"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_eval};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("eval"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_floor};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("floor"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_for};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("for"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_if};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("if"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_lambda};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("lambda"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_ln};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("ln"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_log};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("log"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_not};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("not"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_or};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("or"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_pick};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("pick"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_rand};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("rand"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_roll};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("roll"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_round};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("round"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_seed};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("seed"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_shl};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("shl"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_shr};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("shr"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_sin};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("sin"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_sqrt};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("sqrt"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_swap};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("swap"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_tan};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("tan"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_type_of};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("type_of"), func))
        return FALSE;

    func = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (func == NULL) return FALSE;
    *func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_while};
    if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("while"), func))
        return FALSE;

    LexerInfo lexer_info;
    init_lexer(&lexer_info, SLS_STR("__builtin.sls"), SLS_STR(
        "// Kyler Olsen\n"
        "// YREA SLS\n"
        "// SLS Defined Builtin Operators\n"
        "// November 2025\n"
        "\n"
        "{ ln swap ln swap / } lambda ::logb const\n"
        "{ 1 pick 1 pick < { swap drop } { drop } if } lambda ::max const\n"
        "{ 1 pick 1 pick < { drop } { swap drop } if } lambda ::min const\n"
        "{ 3 1 roll } lambda ::rot const\n"
    ));
    LexerResult result = lexical_analysis(&lexer_info);
    if (result.type == SLS_ERROR) {
        sls_str_free(&result.error.message);
        return FALSE;
    } else {
        LexerTokenResult *head = result.result;
        while (head) {
            if (head->type == SLS_ERROR) {
                sls_str_free(&result.error.message);
                clean_token_result(result.result);
                return FALSE;
            } else if (!execute(interpreter_state, head)) {
                clean_token_result(result.result);
                return FALSE;
            }
            head = head->next;
        }
        clean_token_result(result.result);
    }

    return TRUE;
}

#define NUMERIC_TYPE \
    double af = 0; \
    uint64_t ai = 0; \
    uint64_t type = 0; \
    if (interpreter_state->stack == NULL) return FALSE; \
    \
    switch (interpreter_state->stack->type) { \
    case STACK_IDENTIFIER: \
        return FALSE; \
    case STACK_I64: \
        ai = interpreter_state->stack->i64; \
        af = interpreter_state->stack->i64; \
        type |= NUMERIC_64; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_I32: \
        ai = interpreter_state->stack->i32; \
        af = interpreter_state->stack->i32; \
        type |= NUMERIC_32; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_I16: \
        ai = interpreter_state->stack->i16; \
        af = interpreter_state->stack->i16; \
        type |= NUMERIC_16; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_I8: \
        ai = interpreter_state->stack->i8; \
        af = interpreter_state->stack->i8; \
        type |= NUMERIC_8; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_U64: \
        ai = interpreter_state->stack->u64; \
        af = interpreter_state->stack->u64; \
        type |= NUMERIC_64; \
        break; \
    case STACK_U32: \
        ai = interpreter_state->stack->u32; \
        af = interpreter_state->stack->u32; \
        type |= NUMERIC_32; \
        break; \
    case STACK_U16: \
        ai = interpreter_state->stack->u16; \
        af = interpreter_state->stack->u16; \
        type |= NUMERIC_16; \
        break; \
    case STACK_U8: \
        ai = interpreter_state->stack->u8; \
        af = interpreter_state->stack->u8; \
        type |= NUMERIC_8; \
        break; \
    case STACK_FLOAT: \
        af = interpreter_state->stack->f32; \
        type |= NUMERIC_32; \
        type |= NUMERIC_FLOAT; \
        break; \
    case STACK_DOUBLE: \
        af = interpreter_state->stack->f64; \
        type |= NUMERIC_64; \
        type |= NUMERIC_FLOAT; \
        break; \
    case STACK_CHARACTER: \
        ai = interpreter_state->stack->character; \
        af = interpreter_state->stack->character; \
        break; \
    case STACK_BOOLEAN: \
        ai = interpreter_state->stack->boolean; \
        af = interpreter_state->stack->boolean; \
        break; \
    case STACK_TOKEN_STRING: \
    case STACK_CALLABLE: \
        return FALSE; \
    } \

#define NUMERIC_TYPES \
    double af = 0, bf = 0; \
    uint64_t ai = 0, bi = 0; \
    uint64_t type = 0; \
    if (interpreter_state->stack == NULL) return FALSE; \
    if (interpreter_state->stack->next == NULL) return FALSE; \
    \
    switch (interpreter_state->stack->type) { \
    case STACK_IDENTIFIER: \
        return FALSE; \
    case STACK_I64: \
        ai = interpreter_state->stack->i64; \
        af = interpreter_state->stack->i64; \
        type |= NUMERIC_64; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_I32: \
        ai = interpreter_state->stack->i32; \
        af = interpreter_state->stack->i32; \
        type |= NUMERIC_32; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_I16: \
        ai = interpreter_state->stack->i16; \
        af = interpreter_state->stack->i16; \
        type |= NUMERIC_16; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_I8: \
        ai = interpreter_state->stack->i8; \
        af = interpreter_state->stack->i8; \
        type |= NUMERIC_8; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_U64: \
        ai = interpreter_state->stack->u64; \
        af = interpreter_state->stack->u64; \
        type |= NUMERIC_64; \
        break; \
    case STACK_U32: \
        ai = interpreter_state->stack->u32; \
        af = interpreter_state->stack->u32; \
        type |= NUMERIC_32; \
        break; \
    case STACK_U16: \
        ai = interpreter_state->stack->u16; \
        af = interpreter_state->stack->u16; \
        type |= NUMERIC_16; \
        break; \
    case STACK_U8: \
        ai = interpreter_state->stack->u8; \
        af = interpreter_state->stack->u8; \
        type |= NUMERIC_8; \
        break; \
    case STACK_FLOAT: \
        af = interpreter_state->stack->f32; \
        type |= NUMERIC_32; \
        type |= NUMERIC_FLOAT; \
        break; \
    case STACK_DOUBLE: \
        af = interpreter_state->stack->f64; \
        type |= NUMERIC_64; \
        type |= NUMERIC_FLOAT; \
        break; \
    case STACK_CHARACTER: \
        ai = interpreter_state->stack->character; \
        af = interpreter_state->stack->character; \
        break; \
    case STACK_BOOLEAN: \
        ai = interpreter_state->stack->boolean; \
        af = interpreter_state->stack->boolean; \
        break; \
    case STACK_TOKEN_STRING: \
    case STACK_CALLABLE: \
        return FALSE; \
    } \
    \
    switch (interpreter_state->stack->next->type) { \
    case STACK_IDENTIFIER: \
        return FALSE; \
    case STACK_I64: \
        bi = interpreter_state->stack->next->i64; \
        bf = interpreter_state->stack->next->i64; \
        type |= NUMERIC_64; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_I32: \
        bi = interpreter_state->stack->next->i32; \
        bf = interpreter_state->stack->next->i32; \
        type |= NUMERIC_32; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_I16: \
        bi = interpreter_state->stack->next->i16; \
        bf = interpreter_state->stack->next->i16; \
        type |= NUMERIC_16; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_I8: \
        bi = interpreter_state->stack->next->i8; \
        bf = interpreter_state->stack->next->i8; \
        type |= NUMERIC_8; \
        type |= NUMERIC_SIGNED; \
        break; \
    case STACK_U64: \
        bi = interpreter_state->stack->next->u64; \
        bf = interpreter_state->stack->next->u64; \
        type |= NUMERIC_64; \
        break; \
    case STACK_U32: \
        bi = interpreter_state->stack->next->u32; \
        bf = interpreter_state->stack->next->u32; \
        type |= NUMERIC_32; \
        break; \
    case STACK_U16: \
        bi = interpreter_state->stack->next->u16; \
        bf = interpreter_state->stack->next->u16; \
        type |= NUMERIC_16; \
        break; \
    case STACK_U8: \
        bi = interpreter_state->stack->next->u8; \
        bf = interpreter_state->stack->next->u8; \
        type |= NUMERIC_8; \
        break; \
    case STACK_FLOAT: \
        bf = interpreter_state->stack->next->f32; \
        type |= NUMERIC_32; \
        type |= NUMERIC_FLOAT; \
        break; \
    case STACK_DOUBLE: \
        bf = interpreter_state->stack->next->f64; \
        type |= NUMERIC_64; \
        type |= NUMERIC_FLOAT; \
        break; \
    case STACK_CHARACTER: \
        bi = interpreter_state->stack->next->character; \
        bf = interpreter_state->stack->next->character; \
        break; \
    case STACK_BOOLEAN: \
        bi = interpreter_state->stack->next->boolean; \
        bf = interpreter_state->stack->next->boolean; \
        break; \
    case STACK_TOKEN_STRING: \
    case STACK_CALLABLE: \
        return FALSE; \
    } \

#define FLOAT_FUNCTION(func) \
    (void)ai; \
    (void)type; \
    \
    StackItem *node = interpreter_state->stack; \
    interpreter_state->stack = interpreter_state->stack->next; \
    node->next = NULL; \
    clean_stack(node); \
    \
    return push_token(interpreter_state, (Token){ \
        .type = SLS_FLOAT_BUILTIN_DEFAULT, \
        .double_literal = func(af), \
    }); \

#define ARITHMETIC(op)  \
    StackItem *node = interpreter_state->stack; \
    interpreter_state->stack = interpreter_state->stack->next->next; \
    node->next->next = NULL; \
    clean_stack(node); \
    \
    if (type & NUMERIC_FLOAT && type & NUMERIC_64) { \
        return push_token(interpreter_state, (Token){ \
            .type = TOKEN_DOUBLE, \
            .double_literal = bf op af, \
        }); \
    } else if (type & NUMERIC_FLOAT) { \
        return push_token(interpreter_state, (Token){ \
            .type = TOKEN_FLOAT, \
            .float_literal = (float)bf op (float)af, \
        }); \
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_64) { \
        return push_token(interpreter_state, (Token){ \
            .type = TOKEN_INTEGER, \
            .integer_literal = (IntegerLiteral){ \
                .type = INTEGER_I64, \
                .value = bi op ai, \
            }, \
        }); \
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_32) { \
        return push_token(interpreter_state, (Token){ \
            .type = TOKEN_INTEGER, \
            .integer_literal = (IntegerLiteral){ \
                .type = INTEGER_I32, \
                .value = bi op ai, \
            }, \
        }); \
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_16) { \
        return push_token(interpreter_state, (Token){ \
            .type = TOKEN_INTEGER, \
            .integer_literal = (IntegerLiteral){ \
                .type = INTEGER_I16, \
                .value = bi op ai, \
            }, \
        }); \
    } else if (type & NUMERIC_SIGNED) { \
        return push_token(interpreter_state, (Token){ \
            .type = TOKEN_INTEGER, \
            .integer_literal = (IntegerLiteral){ \
                .type = INTEGER_I8, \
                .value = bi op ai, \
            }, \
        }); \
    } else if (type & NUMERIC_64) { \
        return push_token(interpreter_state, (Token){ \
            .type = TOKEN_INTEGER, \
            .integer_literal = (IntegerLiteral){ \
                .type = INTEGER_U64, \
                .value = bi op ai, \
            }, \
        }); \
    } else if (type & NUMERIC_32) { \
        return push_token(interpreter_state, (Token){ \
            .type = TOKEN_INTEGER, \
            .integer_literal = (IntegerLiteral){ \
                .type = INTEGER_U32, \
                .value = bi op ai, \
            }, \
        }); \
    } else if (type & NUMERIC_16) { \
        return push_token(interpreter_state, (Token){ \
            .type = TOKEN_INTEGER, \
            .integer_literal = (IntegerLiteral){ \
                .type = INTEGER_U16, \
                .value = bi op ai, \
            }, \
        }); \
    } else { \
        return push_token(interpreter_state, (Token){ \
            .type = TOKEN_INTEGER, \
            .integer_literal = (IntegerLiteral){ \
                .type = INTEGER_U8, \
                .value = bi op ai, \
            }, \
        }); \
    } \

#define TRUTHY \
    Boolean value = FALSE; \
    switch (conditional->type) { \
    case STACK_IDENTIFIER: \
        value = FALSE; \
        break; \
    case STACK_I64: \
        value = (conditional->i64) ? TRUE : FALSE; \
        break; \
    case STACK_I32: \
        value = (conditional->i32) ? TRUE : FALSE; \
        break; \
    case STACK_I16: \
        value = (conditional->i16) ? TRUE : FALSE; \
        break; \
    case STACK_I8: \
        value = (conditional->i8) ? TRUE : FALSE; \
        break; \
    case STACK_U64: \
        value = (conditional->u64) ? TRUE : FALSE; \
        break; \
    case STACK_U32: \
        value = (conditional->u32) ? TRUE : FALSE; \
        break; \
    case STACK_U16: \
        value = (conditional->u16) ? TRUE : FALSE; \
        break; \
    case STACK_U8: \
        value = (conditional->u8) ? TRUE : FALSE; \
        break; \
    case STACK_FLOAT: \
        value = (conditional->f32) ? TRUE : FALSE; \
        break; \
    case STACK_DOUBLE: \
        value = (conditional->f64) ? TRUE : FALSE; \
        break; \
    case STACK_CHARACTER: \
        value = (conditional->character) ? TRUE : FALSE; \
        break; \
    case STACK_BOOLEAN: \
        value = conditional->boolean; \
        break; \
    case STACK_TOKEN_STRING: \
    case STACK_CALLABLE: \
        value = (conditional->token_string.length && conditional->token_string.tokens[0].type != TOKEN_EOF) ? TRUE : FALSE; \
        break; \
    } \

#define SCALAR(item, value) \
    switch (item->type) { \
    case STACK_IDENTIFIER: \
        return FALSE; \
    case STACK_I64: \
        if (item->i64 < 0) return FALSE; \
        value = item->i64; \
        break; \
    case STACK_I32: \
        if (item->i32 < 0) return FALSE; \
        value = item->i32; \
        break; \
    case STACK_I16: \
        if (item->i16 < 0) return FALSE; \
        value = item->i16; \
        break; \
    case STACK_I8: \
        if (item->i8 < 0) return FALSE; \
        value = item->i8; \
        break; \
    case STACK_U64: \
        value = item->u64; \
        break; \
    case STACK_U32: \
        value = item->u32; \
        break; \
    case STACK_U16: \
        value = item->u16; \
        break; \
    case STACK_U8: \
        value = item->u8; \
        break; \
    case STACK_FLOAT: \
        return FALSE; \
    case STACK_DOUBLE: \
        return FALSE; \
    case STACK_CHARACTER: \
        value = item->character; \
        break; \
    case STACK_BOOLEAN: \
        value = item->boolean; \
        break; \
    case STACK_TOKEN_STRING: \
    case STACK_CALLABLE: \
        return FALSE; \
    } \

Boolean builtin_addition(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    ARITHMETIC(+);
}

Boolean builtin_subtraction(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    ARITHMETIC(-);
}

Boolean builtin_multiplication(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    ARITHMETIC(*);
}

Boolean builtin_division(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)ai;
    (void)bi;
    (void)type;

    if (af == 0) return FALSE;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    return push_token(interpreter_state, (Token){
        .type = SLS_FLOAT_BUILTIN_DEFAULT,
        .double_literal = bf / af,
    });
}

Boolean builtin_modulus(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)af;
    (void)bf;

    if (type & NUMERIC_FLOAT) {
        return FALSE;
    } else if (ai == 0) {
        return FALSE;
    }

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I64,
                .value = bi % ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I32,
                .value = bi % ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I16,
                .value = bi % ai,
            },
        });
    } else if (type & NUMERIC_SIGNED) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I8,
                .value = bi % ai,
            },
        });
    } else if (type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U64,
                .value = bi % ai,
            },
        });
    } else if (type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U32,
                .value = bi % ai,
            },
        });
    } else if (type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U16,
                .value = bi % ai,
            },
        });
    } else {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U8,
                .value = bi % ai,
            },
        });
    }
}

Boolean builtin_exponential(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)ai;
    (void)bi;
    (void)type;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    return push_token(interpreter_state, (Token){
        .type = SLS_FLOAT_BUILTIN_DEFAULT,
        .double_literal = pow(bf, af),
    });
}

Boolean builtin_greater_than(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)ai;
    (void)bi;
    (void)type;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    return push_token(interpreter_state, (Token){
        .type = TOKEN_BOOLEAN,
        .boolean_literal = bf > af,
    });
}

Boolean builtin_greater_than_or_equal_to(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)ai;
    (void)bi;
    (void)type;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    return push_token(interpreter_state, (Token){
        .type = TOKEN_BOOLEAN,
        .boolean_literal = bf >= af,
    });
}

Boolean builtin_less_than(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)ai;
    (void)bi;
    (void)type;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    return push_token(interpreter_state, (Token){
        .type = TOKEN_BOOLEAN,
        .boolean_literal = bf < af,
    });
}

Boolean builtin_less_than_or_equal_to(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)ai;
    (void)bi;
    (void)type;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    return push_token(interpreter_state, (Token){
        .type = TOKEN_BOOLEAN,
        .boolean_literal = bf <= af,
    });
}

Boolean builtin_equal_to(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)ai;
    (void)bi;
    (void)type;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    return push_token(interpreter_state, (Token){
        .type = TOKEN_BOOLEAN,
        .boolean_literal = bf == af,
    });
}

Boolean builtin_not_equal_to(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)ai;
    (void)bi;
    (void)type;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    return push_token(interpreter_state, (Token){
        .type = TOKEN_BOOLEAN,
        .boolean_literal = bf != af,
    });
}

Boolean builtin_abs(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;

    if (!((type & NUMERIC_SIGNED) | (type & NUMERIC_FLOAT)))
        return FALSE;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next;
    node->next = NULL;
    clean_stack(node);

    if (type & NUMERIC_FLOAT && type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_DOUBLE,
            .double_literal = fabs(af),
        });
    } else if (type & NUMERIC_FLOAT) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_FLOAT,
            .float_literal = fabs(af),
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I64,
                .value = labs((int64_t)ai),
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I32,
                .value = labs((int64_t)ai),
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I16,
                .value = labs((int64_t)ai),
            },
        });
    } else {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I8,
                .value = labs((int64_t)ai),
            },
        });
    }
}

Boolean builtin_acos(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    if (af < -1 || af > 1) return FALSE;
    FLOAT_FUNCTION(acos);
}

Boolean builtin_and(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    if (type & NUMERIC_FLOAT) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_BOOLEAN,
            .boolean_literal = (Boolean){ bf && af },
        });
    } else {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_BOOLEAN,
            .boolean_literal = (Boolean){ bi && ai },
        });
    }
}

Boolean builtin_asin(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    if (af < -1 || af > 1) return FALSE;
    FLOAT_FUNCTION(asin);
}

Boolean builtin_atan(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    FLOAT_FUNCTION(atan);
}

Boolean builtin_atan2(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)ai;
    (void)bi;
    (void)type;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    return push_token(interpreter_state, (Token){
        .type = SLS_FLOAT_BUILTIN_DEFAULT,
        .double_literal = atan2(bf, af),
    });
}

Boolean builtin_bitand(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)af;
    (void)bf;

    if (type & NUMERIC_FLOAT)
        return FALSE;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I64,
                .value = bi & ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I32,
                .value = bi & ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I16,
                .value = bi & ai,
            },
        });
    } else if (type & NUMERIC_SIGNED) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I8,
                .value = bi & ai,
            },
        });
    } else if (type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U64,
                .value = bi & ai,
            },
        });
    } else if (type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U32,
                .value = bi & ai,
            },
        });
    } else if (type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U16,
                .value = bi & ai,
            },
        });
    } else {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U8,
                .value = bi & ai,
            },
        });
    }
}

Boolean builtin_bitnot(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    (void)af;

    if (type & NUMERIC_FLOAT)
        return FALSE;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next;
    node->next = NULL;
    clean_stack(node);

    if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I64,
                .value = ~ ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I32,
                .value = ~ ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I16,
                .value = ~ ai,
            },
        });
    } else if (type & NUMERIC_SIGNED) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I8,
                .value = ~ ai,
            },
        });
    } else if (type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U64,
                .value = ~ ai,
            },
        });
    } else if (type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U32,
                .value = ~ ai,
            },
        });
    } else if (type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U16,
                .value = ~ ai,
            },
        });
    } else {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U8,
                .value = ~ ai,
            },
        });
    }
}

Boolean builtin_bitor(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)af;
    (void)bf;

    if (type & NUMERIC_FLOAT)
        return FALSE;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I64,
                .value = bi | ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I32,
                .value = bi | ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I16,
                .value = bi | ai,
            },
        });
    } else if (type & NUMERIC_SIGNED) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I8,
                .value = bi | ai,
            },
        });
    } else if (type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U64,
                .value = bi | ai,
            },
        });
    } else if (type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U32,
                .value = bi | ai,
            },
        });
    } else if (type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U16,
                .value = bi | ai,
            },
        });
    } else {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U8,
                .value = bi | ai,
            },
        });
    }
}

Boolean builtin_bitxor(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)af;
    (void)bf;

    if (type & NUMERIC_FLOAT)
        return FALSE;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I64,
                .value = bi ^ ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I32,
                .value = bi ^ ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I16,
                .value = bi ^ ai,
            },
        });
    } else if (type & NUMERIC_SIGNED) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I8,
                .value = bi ^ ai,
            },
        });
    } else if (type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U64,
                .value = bi ^ ai,
            },
        });
    } else if (type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U32,
                .value = bi ^ ai,
            },
        });
    } else if (type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U16,
                .value = bi ^ ai,
            },
        });
    } else {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U8,
                .value = bi ^ ai,
            },
        });
    }
}

Boolean builtin_ceil(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    FLOAT_FUNCTION(ceil);
}

Boolean builtin_const(InterpreterState *interpreter_state) {
    if (interpreter_state->stack == NULL) return FALSE;
    StackItem *name = interpreter_state->stack;
    if (name->type != STACK_IDENTIFIER) return FALSE;
    if (name->next == NULL) return FALSE;
    StackItem *item = name->next;
    if (item->type != STACK_CALLABLE) return FALSE;
    if (hash_table_get(interpreter_state->functions, name->identifier.name, NULL) != NULL) return FALSE;

    FunctionItem *function_item = (FunctionItem *)malloc(sizeof(FunctionItem));
    if (function_item == NULL) return FALSE;
    function_item->type = FUNCTION_TOKEN_STRING;
    function_item->token_string = item->token_string;

    interpreter_state->stack = item->next;
    name->next = NULL;

    Boolean return_value = hash_table_put_funcs(interpreter_state->functions, name->identifier.name, function_item);
    clean_stack(name);
    return return_value;
}

Boolean builtin_cos(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    FLOAT_FUNCTION(cos);
}

Boolean builtin_depth(InterpreterState *interpreter_state) {
    size_t depth = 0;
    for (StackItem *node = interpreter_state->stack; node; node = node->next)
        depth++;
    return push_token(interpreter_state, (Token){
        .type = TOKEN_INTEGER,
        .integer_literal = (IntegerLiteral){
            .type = SLS_UNSIGNED_INTEGER_BUILTIN_DEFAULT,
            .value = (uint64_t)depth,
        },
    });
}

Boolean builtin_drop(InterpreterState *interpreter_state) {
    StackItem *node = interpreter_state->stack;
    if (node == NULL) return FALSE;
    interpreter_state->stack = node->next;
    node->next = NULL;
    clean_stack(node);
    return TRUE;
}

Boolean builtin_dup(InterpreterState *interpreter_state) {
    if (interpreter_state->stack == NULL) return FALSE;

    StackItem *item = (StackItem *)malloc(sizeof(StackItem));
    if (item == NULL) return FALSE;
    item->type = interpreter_state->stack->type;
    item->next = interpreter_state->stack;

    switch (interpreter_state->stack->type) {
    case STACK_IDENTIFIER:
        item->identifier = interpreter_state->stack->identifier;
        break;
    case STACK_I64:
        item->i64 = interpreter_state->stack->i64;
        break;
    case STACK_I32:
        item->i32 = interpreter_state->stack->i32;
        break;
    case STACK_I16:
        item->i16 = interpreter_state->stack->i16;
        break;
    case STACK_I8:
        item->i8 = interpreter_state->stack->i8;
        break;
    case STACK_U64:
        item->u64 = interpreter_state->stack->u64;
        break;
    case STACK_U32:
        item->u32 = interpreter_state->stack->u32;
        break;
    case STACK_U16:
        item->u16 = interpreter_state->stack->u16;
        break;
    case STACK_U8:
        item->u8 = interpreter_state->stack->u8;
        break;
    case STACK_FLOAT:
        item->f32 = interpreter_state->stack->f32;
        break;
    case STACK_DOUBLE:
        item->f64 = interpreter_state->stack->f64;
        break;
    case STACK_CHARACTER:
        item->character = interpreter_state->stack->character;
        break;
    case STACK_BOOLEAN:
        item->boolean = interpreter_state->stack->boolean;
        break;
    case STACK_TOKEN_STRING:
    case STACK_CALLABLE:
        item->token_string = copy_token_string(interpreter_state->stack->token_string);
        break;
    }

    interpreter_state->stack = item;
    return TRUE;
}

Boolean builtin_eval(InterpreterState *interpreter_state) {
    if (interpreter_state->stack == NULL) return FALSE;
    StackItem *code_target = interpreter_state->stack;

    interpreter_state->stack = code_target->next;
    code_target->next = NULL;

    Boolean return_value = FALSE;
    if (code_target->type == STACK_TOKEN_STRING || code_target->type == STACK_CALLABLE)
        return_value = execute_token_string(interpreter_state, code_target->token_string);
    else if (code_target->type == STACK_IDENTIFIER)
        return_value = execute_func(interpreter_state, code_target->identifier.name);

    clean_stack(code_target);
    return return_value;
}

Boolean builtin_floor(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    FLOAT_FUNCTION(floor);
}

Boolean builtin_for(InterpreterState *interpreter_state) {
    if (interpreter_state->stack == NULL) return FALSE;
    StackItem *for_block = interpreter_state->stack;
    if (for_block->next == NULL) return FALSE;
    StackItem *end_item = for_block->next;
    if (end_item->next == NULL) return FALSE;
    StackItem *start_item = end_item->next;

    if (!(
        for_block->type == STACK_TOKEN_STRING ||
        for_block->type == STACK_CALLABLE ||
        for_block->type == STACK_IDENTIFIER
    )) return FALSE;

    interpreter_state->stack = start_item->next;
    start_item->next = NULL;

    size_t start_value;
    SCALAR(start_item, start_value);
    size_t end_value;
    SCALAR(end_item, end_value);

    Boolean return_value = FALSE;
    for (size_t i = start_value; i < end_value; i++) {
        return_value = push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = SLS_INTEGER_BUILTIN_DEFAULT,
                .value = (uint64_t)i,
            },
        });
        if (!return_value) break;

        if (for_block->type == STACK_TOKEN_STRING || for_block->type == STACK_CALLABLE)
            return_value = execute_token_string(interpreter_state, for_block->token_string);
        else if (for_block->type == STACK_IDENTIFIER)
            return_value = execute_func(interpreter_state, for_block->identifier.name);
        if (!return_value) break;
    }

    clean_stack(for_block);
    return return_value;
}

Boolean builtin_if(InterpreterState *interpreter_state) {
    if (interpreter_state->stack == NULL) return FALSE;
    StackItem *else_block = interpreter_state->stack;
    if (else_block->next == NULL) return FALSE;
    StackItem *then_block = else_block->next;
    if (then_block->next == NULL) return FALSE;
    StackItem *conditional = then_block->next;

    if (!(
        else_block->type == STACK_TOKEN_STRING ||
        else_block->type == STACK_CALLABLE ||
        else_block->type == STACK_IDENTIFIER
    )) return FALSE;

    if (!(
        then_block->type == STACK_TOKEN_STRING ||
        then_block->type == STACK_CALLABLE ||
        then_block->type == STACK_IDENTIFIER
    )) return FALSE;

    interpreter_state->stack = conditional->next;
    conditional->next = NULL;

    TRUTHY;

    Boolean return_value = FALSE;
    if (value) {
        if (then_block->type == STACK_TOKEN_STRING || then_block->type == STACK_CALLABLE)
            return_value = execute_token_string(interpreter_state, then_block->token_string);
        else if (then_block->type == STACK_IDENTIFIER)
            return_value = execute_func(interpreter_state, then_block->identifier.name);
    } else {
        if (else_block->type == STACK_TOKEN_STRING || else_block->type == STACK_CALLABLE)
            return_value = execute_token_string(interpreter_state, else_block->token_string);
        else if (else_block->type == STACK_IDENTIFIER)
            return_value = execute_func(interpreter_state, else_block->identifier.name);
    }

    clean_stack(else_block);
    return return_value;
}

Boolean builtin_lambda(InterpreterState *interpreter_state) {
    if (interpreter_state->stack == NULL) return FALSE;
    if (interpreter_state->stack->type != STACK_TOKEN_STRING) return FALSE;
    interpreter_state->stack->type = STACK_CALLABLE;
    return TRUE;
}

Boolean builtin_ln(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    if (af <= 0) return FALSE;
    FLOAT_FUNCTION(log);
}

Boolean builtin_log(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    if (af <= 0) return FALSE;
    FLOAT_FUNCTION(log10);
}

Boolean builtin_not(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    if (type & NUMERIC_FLOAT) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_BOOLEAN,
            .boolean_literal = (Boolean){ !af },
        });
    } else {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_BOOLEAN,
            .boolean_literal = (Boolean){ !ai },
        });
    }
}

Boolean builtin_or(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    if (type & NUMERIC_FLOAT) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_BOOLEAN,
            .boolean_literal = (Boolean){ bf || af },
        });
    } else {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_BOOLEAN,
            .boolean_literal = (Boolean){ bi || ai },
        });
    }
}

Boolean builtin_pick(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    (void)af;

    if (type & NUMERIC_FLOAT)
        return FALSE;

    StackItem *picked = interpreter_state->stack->next;
    for (size_t i = 0; i < ai; i++) {
        picked = picked->next;
        if (picked == NULL) return FALSE;
    }

    if (picked == NULL) return FALSE;

    StackItem *node = interpreter_state->stack;
    if (node == NULL) return FALSE;
    interpreter_state->stack = node->next;
    node->next = NULL;
    clean_stack(node);

    StackItem *item = (StackItem *)malloc(sizeof(StackItem));
    if (item == NULL) return FALSE;
    item->type = picked->type;
    item->next = interpreter_state->stack;

    switch (interpreter_state->stack->type) {
    case STACK_IDENTIFIER:
        item->identifier = picked->identifier;
        break;
    case STACK_I64:
        item->i64 = picked->i64;
        break;
    case STACK_I32:
        item->i32 = picked->i32;
        break;
    case STACK_I16:
        item->i16 = picked->i16;
        break;
    case STACK_I8:
        item->i8 = picked->i8;
        break;
    case STACK_U64:
        item->u64 = picked->u64;
        break;
    case STACK_U32:
        item->u32 = picked->u32;
        break;
    case STACK_U16:
        item->u16 = picked->u16;
        break;
    case STACK_U8:
        item->u8 = picked->u8;
        break;
    case STACK_FLOAT:
        item->f32 = picked->f32;
        break;
    case STACK_DOUBLE:
        item->f64 = picked->f64;
        break;
    case STACK_CHARACTER:
        item->character = picked->character;
        break;
    case STACK_BOOLEAN:
        item->boolean = picked->boolean;
        break;
    case STACK_TOKEN_STRING:
    case STACK_CALLABLE:
        item->token_string = copy_token_string(picked->token_string);
        break;
    }

    interpreter_state->stack = item;
    return TRUE;
}

Boolean builtin_rand(InterpreterState *interpreter_state) {
    return push_token(interpreter_state, (Token){
        .type = SLS_FLOAT_BUILTIN_DEFAULT,
        .double_literal = rand() / RAND_MAX,
    });
}

Boolean builtin_roll(InterpreterState *interpreter_state) {
    if (interpreter_state->stack == NULL) return FALSE;
    if (interpreter_state->stack->next == NULL) return FALSE;

    StackItem *times_item = interpreter_state->stack;
    StackItem *count_item = times_item->next;

    size_t times;
    SCALAR(times_item, times);

    size_t count;
    SCALAR(count_item, count);

    StackItem *head = NULL, *tail = NULL, *prev = NULL;
    if (count > 0) {
        StackItem *node = count_item->next;
        for (size_t i = 0; i < count; i++) {
            if (node == NULL) return FALSE;
            if (i == (count - times) - 1) {
                tail = node;
                head = node->next;
            }
            prev = node;
            node = node->next;
        }
    }

    if (head == NULL || tail == NULL) return FALSE;

    interpreter_state->stack = head;
    tail->next = prev->next;
    prev->next = count_item->next;
    count_item->next = NULL;
    clean_stack(times_item);

    return TRUE;
}

Boolean builtin_round(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    FLOAT_FUNCTION(round);
}

Boolean builtin_seed(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    (void)af;

    if (type & NUMERIC_FLOAT) {
        return FALSE;
    }

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next;
    node->next = NULL;
    clean_stack(node);

    srand(ai);
    return TRUE;
}

Boolean builtin_shl(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)af;
    (void)bf;

    if (type & NUMERIC_FLOAT)
        return FALSE;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I64,
                .value = bi << ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I32,
                .value = bi << ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I16,
                .value = bi << ai,
            },
        });
    } else if (type & NUMERIC_SIGNED) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I8,
                .value = bi << ai,
            },
        });
    } else if (type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U64,
                .value = bi << ai,
            },
        });
    } else if (type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U32,
                .value = bi << ai,
            },
        });
    } else if (type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U16,
                .value = bi << ai,
            },
        });
    } else {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U8,
                .value = bi << ai,
            },
        });
    }
}

Boolean builtin_shr(InterpreterState *interpreter_state) {
    NUMERIC_TYPES;
    (void)af;
    (void)bf;

    if (type & NUMERIC_FLOAT)
        return FALSE;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next->next;
    node->next->next = NULL;
    clean_stack(node);

    if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I64,
                .value = bi >> ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I32,
                .value = bi >> ai,
            },
        });
    } else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I16,
                .value = bi >> ai,
            },
        });
    } else if (type & NUMERIC_SIGNED) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_I8,
                .value = bi >> ai,
            },
        });
    } else if (type & NUMERIC_64) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U64,
                .value = bi >> ai,
            },
        });
    } else if (type & NUMERIC_32) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U32,
                .value = bi >> ai,
            },
        });
    } else if (type & NUMERIC_16) {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U16,
                .value = bi >> ai,
            },
        });
    } else {
        return push_token(interpreter_state, (Token){
            .type = TOKEN_INTEGER,
            .integer_literal = (IntegerLiteral){
                .type = INTEGER_U8,
                .value = bi >> ai,
            },
        });
    }
}

Boolean builtin_sin(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    FLOAT_FUNCTION(sin);
}

Boolean builtin_sqrt(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    if (af < 0) return FALSE;
    FLOAT_FUNCTION(sqrt);
}

Boolean builtin_swap(InterpreterState *interpreter_state) {
    if (interpreter_state->stack == NULL) return FALSE;
    if (interpreter_state->stack->next == NULL) return FALSE;

    StackItem *a = interpreter_state->stack;
    StackItem *b = a->next;

    a->next = b->next;
    b->next = a;
    interpreter_state->stack = b;

    return TRUE;
}

Boolean builtin_tan(InterpreterState *interpreter_state) {
    NUMERIC_TYPE;
    FLOAT_FUNCTION(tan);
}

Boolean builtin_type_of(InterpreterState *interpreter_state) {
    if (interpreter_state->stack == NULL)
        return FALSE;

    StackItem *node = interpreter_state->stack;
    interpreter_state->stack = interpreter_state->stack->next;
    node->next = NULL;

    Boolean return_value = push_token(interpreter_state, (Token){
        .type = TOKEN_IDENTIFIER,
        .identifier = (Identifier){
            .is_literal = TRUE,
            .name = sls_str_malloc(STACK_TYPES_TYPES[node->type], TYPE_NAMES_SAFE_LENGTH),
        },
    });

    clean_stack(node);
    return return_value;
}

Boolean builtin_while(InterpreterState *interpreter_state) {
    if (interpreter_state->stack == NULL) return FALSE;
    StackItem *while_block = interpreter_state->stack;
    if (while_block->next == NULL) return FALSE;
    StackItem *conditional_block = while_block->next;

    if (!(
        while_block->type == STACK_TOKEN_STRING ||
        while_block->type == STACK_CALLABLE ||
        while_block->type == STACK_IDENTIFIER
    )) return FALSE;

    if (!(
        conditional_block->type == STACK_TOKEN_STRING ||
        conditional_block->type == STACK_CALLABLE ||
        conditional_block->type == STACK_IDENTIFIER
    )) return FALSE;

    interpreter_state->stack = conditional_block->next;
    conditional_block->next = NULL;

    Boolean return_value = FALSE;
    while (TRUE) {
        if (conditional_block->type == STACK_TOKEN_STRING || conditional_block->type == STACK_CALLABLE)
            return_value = execute_token_string(interpreter_state, conditional_block->token_string);
        else if (conditional_block->type == STACK_IDENTIFIER)
            return_value = execute_func(interpreter_state, conditional_block->identifier.name);
        if (!return_value) break;
        if (interpreter_state->stack == NULL) return FALSE;

        StackItem *conditional = interpreter_state->stack;
        interpreter_state->stack = conditional->next;
        conditional->next = NULL;
        TRUTHY;
        clean_stack(conditional);
        if (!value) break;

        if (while_block->type == STACK_TOKEN_STRING || while_block->type == STACK_CALLABLE)
            return_value = execute_token_string(interpreter_state, while_block->token_string);
        else if (while_block->type == STACK_IDENTIFIER)
            return_value = execute_func(interpreter_state, while_block->identifier.name);
        if (!return_value) break;
    }

    clean_stack(while_block);
    return return_value;
}
