Ancient

 view release on metacpan or  search on metacpan

xs/const/const.c  view on Meta::CPAN

                    if (constval && PL_comppad) {
                        SV **svp = av_fetch(PL_comppad, po, 1);
                        if (svp) {
                            sv_setsv(*svp, constval);
                        }
                    }
                }
            }
        }

        /* Convert our custom op to a regular OP_CONST for runtime */
        rhs->op_type = OP_CONST;
        rhs->op_ppaddr = PL_ppaddr[OP_CONST];
    }

call_orig:
    return orig_ck_sassign(aTHX_ o);
}

/* ============================================
   Call checker for c() - constant folding
   ============================================ */

static OP* const_c_call_checker(pTHX_ OP *entersubop, GV *namegv, SV *ckobj) {
    OP *pushop, *cvop, *argop;
    PERL_UNUSED_ARG(namegv);
    PERL_UNUSED_ARG(ckobj);

    /* Navigate the op tree to find arguments */
    pushop = cUNOPx(entersubop)->op_first;
    if (!OpHAS_SIBLING(pushop)) {
        pushop = cUNOPx(pushop)->op_first;
    }

    /* First arg after pushmark */
    argop = OpSIBLING(pushop);

    /* Find cv op (last sibling) */
    cvop = argop;
    while (OpHAS_SIBLING(cvop)) {
        cvop = OpSIBLING(cvop);
    }

    /* Check if single constant argument */
    if (argop != cvop && OpSIBLING(argop) == cvop) {
        /* We have exactly one argument */
        if (argop->op_type == OP_CONST) {
            /* Constant argument - replace entire call with our custom
             * confold_marker op. This allows my_ck_sassign to detect it
             * and set PADNAMEf_CONST on the target pad entry. */
            SV *val = cSVOPx_sv(argop);
            SV *newval = newSVsv(val);
            OP *markerop;

            /* Make it deeply readonly if it's a reference */
            if (SvROK(newval)) {
                _make_readonly(aTHX_ SvRV(newval));
            }
            SvREADONLY_on(newval);

            /* Create a custom op that looks like SVOP but uses our pp func */
            markerop = newSVOP(OP_CUSTOM, 0, newval);
            markerop->op_ppaddr = pp_confold_marker;

            op_free(entersubop);
            return markerop;
        }
        /* Non-constant arg - fall through to XS for runtime evaluation */
    }

    /* Fall through to XS implementation */
    return entersubop;
}

/* ============================================
   XS Functions
   ============================================ */

XS_EXTERNAL(XS_const_c);
XS_EXTERNAL(XS_const_c) {
    dXSARGS;
    SV *val, *result;

    if (items != 1) {
        croak("Usage: const::c(VALUE)");
    }

    val = ST(0);

    /* Create a copy and make it readonly */
    if (SvROK(val)) {
        /* For refs, make deep copy and make deeply readonly */
        result = newSVsv(val);
        _make_readonly(aTHX_ SvRV(result));
        SvREADONLY_on(result);
    } else {
        result = newSVsv(val);
        SvREADONLY_on(result);
    }

    /* Return mortal - caller's assignment will increase refcount */
    ST(0) = sv_2mortal(result);
    XSRETURN(1);
}

/* const() uses prototype \[$@%]@ to get reference to target variable */
XS_EXTERNAL(XS_const_const);
XS_EXTERNAL(XS_const_const) {
    dXSARGS;
    SV *ref;
    int type;
    int i;

    if (items < 2) {
        croak("No value for readonly variable");
    }

    ref = ST(0);
    if (!SvROK(ref)) {
        croak("First argument must be a reference (use: const my $x => value)");
    }



( run in 0.496 second using v1.01-cache-2.11-cpan-5a3173703d6 )