<commit_before>#define MVM_SHARED 1
#include "moar.h"
#include "container.h"

/* Dummy, no-arg callsite. */
static MVMCallsite no_arg_callsite = { NULL, 0, 0, 0 };

/* Dummy callsite for type_check. */
static MVMCallsiteEntry tc_flags[] = { MVM_CALLSITE_ARG_OBJ,
                                       MVM_CALLSITE_ARG_OBJ,
                                       MVM_CALLSITE_ARG_OBJ };
static MVMCallsite     tc_callsite = { tc_flags, 3, 3, 0 };

static void rakudo_scalar_fetch(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
    res->o = ((Rakudo_Scalar *)cont)->value;
}

MVMObject * get_nil();
MVMObject * get_mu();

static void finish_store(MVMThreadContext *tc, MVMObject *cont, MVMObject *obj) {
    Rakudo_Scalar *rs = (Rakudo_Scalar *)cont;
    MVMObject *whence;

    /* Store the value. */
    MVM_ASSIGN_REF(tc, cont, rs->value, obj);

    /* Run any whence closure. */
    whence = rs->whence;
    if (whence && IS_CONCRETE(whence)) {
        MVMObject *code = MVM_frame_find_invokee(tc, whence, NULL);
        MVM_args_setup_thunk(tc, NULL, MVM_RETURN_VOID, &no_arg_callsite);
        rs->whence = NULL;
        STABLE(code)->invoke(tc, code, &no_arg_callsite, tc->cur_frame->args);
    }
}

static void typecheck_failed(MVMThreadContext *tc, MVMObject *cont, MVMObject *obj) {
    /* XXX TODO: Improve this error reporting by looking up typed thrower. */
    MVM_exception_throw_adhoc(tc, "Type check failed in assignment");
}

typedef struct {
    MVMObject   *cont;
    MVMObject   *obj;
    MVMRegister  res;
} type_check_data;
static void type_check_ret(MVMThreadContext *tc, void *sr_data) {
    type_check_data *tcd = (type_check_data *)sr_data;
    MVMObject *cont = tcd->cont;
    MVMObject *obj  = tcd->obj;
    MVMint64   res  = tcd->res.i64;
    free(tcd);
    if (res)
        finish_store(tc, cont, obj);
    else
        typecheck_failed(tc, cont, obj);
}
static void mark_sr_data(MVMThreadContext *tc, MVMFrame *frame, MVMGCWorklist *worklist) {
    type_check_data *tcd = (type_check_data *)frame->special_return_data;
    MVM_gc_worklist_add(tc, worklist, &tcd->cont);
    MVM_gc_worklist_add(tc, worklist, &tcd->obj);
}

static void rakudo_scalar_store(MVMThreadContext *tc, MVMObject *cont, MVMObject *obj) {
    Rakudo_Scalar *rs = (Rakudo_Scalar *)cont;
    Rakudo_ContainerDescriptor *rcd = (Rakudo_ContainerDescriptor *)rs->descriptor;
    MVMint64 rw = 0;

    /* Check it's an assignable container. */
    if (rcd)
        rw = rcd->rw;
    if (!rw)
        MVM_exception_throw_adhoc(tc, "Cannot assign to a readonly variable or a value");

    /* Handle Nil and type-checking. */
    if (!obj) {
        MVM_exception_throw_adhoc(tc, "Cannot assign a null value to a Perl 6 scalar");
    }
    else if (STABLE(obj)->WHAT == get_nil()) {
        if (rcd) {
            obj = rcd->the_default;
        }
    }
    else {
        /* Check against the type-check cache first (common, fast-path
         * case). */
        MVMint64 mode = STABLE(rcd->of)->mode_flags & MVM_TYPE_CHECK_CACHE_FLAG_MASK;
        if (rcd->of != get_mu() && !MVM_6model_istype_cache_only(tc, obj, rcd->of)) {
            /* Failed. If the cache is definitive, we certainly have an error. */
            if ((mode & MVM_TYPE_CHECK_CACHE_THEN_METHOD) == 0 &&
                (mode & MVM_TYPE_CHECK_NEEDS_ACCEPTS) == 0)
                typecheck_failed(tc, cont, obj);

            /* If we get here, need to call .^type_check on the value we're
             * checking, unless it's an accepts check. */
            if (!STABLE(obj)->type_check_cache || (mode & MVM_TYPE_CHECK_CACHE_THEN_METHOD)) {
                MVMObject *HOW = STABLE(rcd->of)->HOW;
                MVMObject *meth = MVM_6model_find_method_cache_only(tc, HOW,
                    tc->instance->str_consts.type_check);
                if (meth) {
                    /* Set up the call, using a fake register in special return
                     * data as the target. */<commit_msg>Add missing concreteness check; fixes a SEGV.<commit_after>#define MVM_SHARED 1
#include "moar.h"
#include "container.h"

/* Dummy, no-arg callsite. */
static MVMCallsite no_arg_callsite = { NULL, 0, 0, 0 };

/* Dummy callsite for type_check. */
static MVMCallsiteEntry tc_flags[] = { MVM_CALLSITE_ARG_OBJ,
                                       MVM_CALLSITE_ARG_OBJ,
                                       MVM_CALLSITE_ARG_OBJ };
static MVMCallsite     tc_callsite = { tc_flags, 3, 3, 0 };

static void rakudo_scalar_fetch(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
    res->o = ((Rakudo_Scalar *)cont)->value;
}

MVMObject * get_nil();
MVMObject * get_mu();

static void finish_store(MVMThreadContext *tc, MVMObject *cont, MVMObject *obj) {
    Rakudo_Scalar *rs = (Rakudo_Scalar *)cont;
    MVMObject *whence;

    /* Store the value. */
    MVM_ASSIGN_REF(tc, cont, rs->value, obj);

    /* Run any whence closure. */
    whence = rs->whence;
    if (whence && IS_CONCRETE(whence)) {
        MVMObject *code = MVM_frame_find_invokee(tc, whence, NULL);
        MVM_args_setup_thunk(tc, NULL, MVM_RETURN_VOID, &no_arg_callsite);
        rs->whence = NULL;
        STABLE(code)->invoke(tc, code, &no_arg_callsite, tc->cur_frame->args);
    }
}

static void typecheck_failed(MVMThreadContext *tc, MVMObject *cont, MVMObject *obj) {
    /* XXX TODO: Improve this error reporting by looking up typed thrower. */
    MVM_exception_throw_adhoc(tc, "Type check failed in assignment");
}

typedef struct {
    MVMObject   *cont;
    MVMObject   *obj;
    MVMRegister  res;
} type_check_data;
static void type_check_ret(MVMThreadContext *tc, void *sr_data) {
    type_check_data *tcd = (type_check_data *)sr_data;
    MVMObject *cont = tcd->cont;
    MVMObject *obj  = tcd->obj;
    MVMint64   res  = tcd->res.i64;
    free(tcd);
    if (res)
        finish_store(tc, cont, obj);
    else
        typecheck_failed(tc, cont, obj);
}
static void mark_sr_data(MVMThreadContext *tc, MVMFrame *frame, MVMGCWorklist *worklist) {
    type_check_data *tcd = (type_check_data *)frame->special_return_data;
    MVM_gc_worklist_add(tc, worklist, &tcd->cont);
    MVM_gc_worklist_add(tc, worklist, &tcd->obj);
}

static void rakudo_scalar_store(MVMThreadContext *tc, MVMObject *cont, MVMObject *obj) {
    Rakudo_Scalar *rs = (Rakudo_Scalar *)cont;
    Rakudo_ContainerDescriptor *rcd = (Rakudo_ContainerDescriptor *)rs->descriptor;
    MVMint64 rw = 0;

    /* Check it's an assignable container. */
    if (rcd && IS_CONCRETE(rcd))
        rw = rcd->rw;
    if (!rw)
        MVM_exception_throw_adhoc(tc, "Cannot assign to a readonly variable or a value");

    /* Handle Nil and type-checking. */
    if (!obj) {
        MVM_exception_throw_adhoc(tc, "Cannot assign a null value to a Perl 6 scalar");
    }
    else if (STABLE(obj)->WHAT == get_nil()) {
        obj = rcd->the_default;
    }
    else {
        /* Check against the type-check cache first (common, fast-path
         * case). */
        MVMint64 mode = STABLE(rcd->of)->mode_flags & MVM_TYPE_CHECK_CACHE_FLAG_MASK;
        if (rcd->of != get_mu() && !MVM_6model_istype_cache_only(tc, obj, rcd->of)) {
            /* Failed. If the cache is definitive, we certainly have an error. */
            if ((mode & MVM_TYPE_CHECK_CACHE_THEN_METHOD) == 0 &&
                (mode & MVM_TYPE_CHECK_NEEDS_ACCEPTS) == 0)
                typecheck_failed(tc, cont, obj);

            /* If we get here, need to call .^type_check on the value we're
             * checking, unless it's an accepts check. */
            if (!STABLE(obj)->type_check_cache || (mode & MVM_TYPE_CHECK_CACHE_THEN_METHOD)) {
                MVMObject *HOW = STABLE(rcd->of)->HOW;
                MVMObject *meth = MVM_6model_find_method_cache_only(tc, HOW,
                    tc->instance->str_consts.type_check);
                if (meth) {
                    /* Set up the call, using a fake register in special return
                     * data as the target. */
{'fraction_non_alphanumeric': 0.1161128526645768, 'fraction_numerical': 0.005266457680250784, 'mean_word_length': 2.7481203007518795, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '636720', 'n_tokens_mistral': 2840, 'n_tokens_neox': 2738, 'n_words': 665}