SV *
name(self)
SV *self
ALIAS:
name = 0
sigil = 1
class = 2
CODE:
{
FieldMeta *meta = NUM2PTR(FieldMeta *, SvUV(SvRV(self)));
switch(ix) {
case 0:
RETVAL = SvREFCNT_inc(meta->name);
break;
case 1:
RETVAL = newSVpvn(SvPVX(meta->name), 1);
break;
case 2:
RETVAL = newSV(0);
sv_setref_uv(RETVAL, "Object::Pad::MOP::Class", PTR2UV(meta->class));
break;
default: RETVAL = NULL;
}
}
OUTPUT:
RETVAL
void
value(self, obj)
SV *self
SV *obj
PPCODE:
{
FieldMeta *meta = NUM2PTR(FieldMeta *, SvUV(SvRV(self)));
ClassMeta *classmeta = meta->class;
SV *objrv;
if(!SvROK(obj) || !SvOBJECT(objrv = SvRV(obj)))
croak("Cannot fetch field value of a non-instance");
AV *backingav;
FIELDOFFSET fieldix;
if(classmeta->type == METATYPE_ROLE) {
HV *objstash = SvSTASH(objrv);
const char *key = HvNAME(objstash);
STRLEN klen = HvNAMELEN(objstash);
if(HvNAMEUTF8(objstash))
klen = -klen;
assert(key);
SV **svp = hv_fetch(classmeta->role.applied_classes, key, klen, 0);
if(!svp)
croak("Cannot fetch role field value from a non-applied instance");
RoleEmbedding *embedding = (RoleEmbedding *)*svp;
backingav = (AV *)get_obj_backingav(obj, embedding->classmeta->repr, true);
fieldix = meta->fieldix + embedding->offset;
}
else {
const char *stashname = HvNAME(classmeta->stash);
if(!stashname || !sv_derived_from(obj, stashname))
croak("Cannot fetch field value from a non-derived instance");
backingav = (AV *)get_obj_backingav(obj, classmeta->repr, true);
fieldix = meta->fieldix;
}
if(fieldix > av_top_index(backingav))
croak("ARGH: instance does not have a field at index %ld", (long int)fieldix);
SV *value = AvARRAY(backingav)[fieldix];
/* We must prevent caller from assigning to non-scalar fields, in case
* they break the SvTYPE of the value. We can't cancel the CvLVALUE but we
* can yield a READONLY value in this case */
if(SvPV_nolen(meta->name)[0] != '$') {
value = sv_mortalcopy(value);
SvREADONLY_on(value);
}
/* stack does not contribute SvREFCNT */
ST(0) = value;
XSRETURN(1);
}
bool
has_attribute(self, name)
SV *self
SV *name
CODE:
{
FieldMeta *meta = NUM2PTR(FieldMeta *, SvUV(SvRV(self)));
const struct FieldHook *hook = mop_field_get_attribute(meta, SvPV_nolen(name));
RETVAL = !!hook;
}
OUTPUT:
RETVAL
SV *
get_attribute_value(self, name)
SV *self
SV *name
CODE:
{
FieldMeta *meta = NUM2PTR(FieldMeta *, SvUV(SvRV(self)));
const struct FieldHook *hook = mop_field_get_attribute(meta, SvPV_nolen(name));
if(!hook)
croak("Field does not have an attribute called %" SVf, SVfARG(name));
RETVAL = newSVsv(hook->hookdata);
}
OUTPUT:
RETVAL
void
get_attribute_values(self, name)
SV *self
SV *name
PPCODE:
{
FieldMeta *meta = NUM2PTR(FieldMeta *, SvUV(SvRV(self)));
AV *values = mop_field_get_attribute_values(meta, SvPV_nolen(name));
if(!values)
croak("Field does not have an attribute called %" SVf, SVfARG(name));
Size_t count = av_count(values);
EXTEND(SP, count);
for(Size_t i = 0; i < count; i++)
PUSHs(SvREFCNT_inc(AvARRAY(values)[i]));
SvREFCNT_dec(values);
XSRETURN(count);
}