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 )