Object-Pad
view release on metacpan or search on metacpan
src/class.c view on Meta::CPAN
ops = op_append_list(OP_LINESEQ, ops,
methstartop = newMETHSTARTOP(OPf_STACKED | opflags_if_role | (meta->repr << 8))
);
else
ops = op_append_list(OP_LINESEQ, ops,
methstartop = newCOMMONMETHSTARTOP(OPf_STACKED | (meta->repr << 8)));
}
if(!is_common) {
AV *fieldmap = newAV();
U32 fieldcount = 0, max_fieldix = 0;
SAVEFREESV((SV *)fieldmap);
PADNAME **padnames = PadnamelistARRAY(PadlistNAMES(CvPADLIST(PL_compcv)));
U32 cop_seq_low = COP_SEQ_RANGE_LOW(padnames[PADIX_SELF]);
int i;
for(i = 0; i < nfields; i++) {
FieldMeta *fieldmeta = MUST_FIELDMETA(AvARRAY(fields)[i]);
if(snames) {
PADNAME *fieldname = snames[i + 1];
if(!fieldname || PadnameREFCNT(fieldname) < 2)
continue;
}
/* TODO: Find a better test for initfields so it doesn't think we capture
* every field declared up til now. */
FIELDOFFSET fieldix = fieldmeta->fieldix;
PADOFFSET padix = outerscope ? find_padix_for_field(fieldmeta)
: pad_findmy_pv(SvPVX(fieldmeta->name), 0);
if(padix == NOT_IN_PAD)
continue;
U8 private = 0;
switch(SvPV_nolen(fieldmeta->name)[0]) {
case '$': private = OPpFIELDPAD_SV; break;
case '@': private = OPpFIELDPAD_AV; break;
case '%': private = OPpFIELDPAD_HV; break;
}
PERL_UNUSED_VAR(opflags_if_role);
assert((fieldix & ~FIELDIX_MASK) == 0);
av_store(fieldmap, padix, newSVuv(((UV)private << FIELDIX_TYPE_SHIFT) | fieldix));
fieldcount++;
if(fieldix > max_fieldix)
max_fieldix = fieldix;
if(snames) {
PADNAME *fieldname = snames[i + 1];
/* Unshare the padname so the one in the methodscope pad returns to refcount 1 */
PADNAME *newpadname = newPADNAMEpvn(PadnamePV(fieldname), PadnameLEN(fieldname));
PadnameREFCNT_dec(padnames[padix]);
padnames[padix] = newpadname;
/* Turn off OUTER and set a valid COP sequence range, so the lexical is
* visible to eval(), PadWalker, perldb, etc.. */
PadnameOUTER_off(newpadname);
COP_SEQ_RANGE_LOW(newpadname) = cop_seq_low;
COP_SEQ_RANGE_HIGH(newpadname) = PL_cop_seqmax;
}
}
if(fieldcount) {
UNOP_AUX_item *aux;
Newx(aux, 2 + fieldcount*2, UNOP_AUX_item);
cUNOP_AUXx(methstartop)->op_aux = aux;
(aux++)->uv = fieldcount;
(aux++)->uv = max_fieldix;
for(Size_t i = 0; i < av_count(fieldmap); i++) {
if(!AvARRAY(fieldmap)[i] || !SvOK(AvARRAY(fieldmap)[i]))
continue;
(aux++)->uv = i;
(aux++)->uv = SvUV(AvARRAY(fieldmap)[i]);
}
}
}
return op_append_list(OP_LINESEQ, ops, body);
}
OP *ObjectPad__finish_method_parse(pTHX_ ClassMeta *meta, bool is_common, OP *body)
{
assert(meta->methodscope && SvTYPE(meta->methodscope) == SVt_PVCV);
/* If we have no body that means this was a bodyless method
* declaration; a required method for a role
*/
if(body && !is_common) {
{
ENTER;
SAVEVPTR(PL_curcop);
PADNAME **padnames = PadnamelistARRAY(PadlistNAMES(CvPADLIST(PL_compcv)));
/* See https://rt.cpan.org/Ticket/Display.html?id=132428
* https://github.com/Perl/perl5/issues/17754
*/
PADOFFSET padix;
for(padix = PADIX_SELF + 1; padix <= PadnamelistMAX(PadlistNAMES(CvPADLIST(PL_compcv))); padix++) {
PADNAME *pn = padnames[padix];
if(PadnameIsNULL(pn) || !PadnameLEN(pn))
continue;
const char *pv = PadnamePV(pn);
if(!pv || !strEQ(pv, "$self"))
continue;
COP *padcop = NULL;
if(find_cop_for_lvintro(padix, body, &padcop))
PL_curcop = padcop;
warn("\"my\" variable $self masks earlier declaration in same scope");
}
( run in 1.068 second using v1.01-cache-2.11-cpan-39bf76dae61 )