4 static MGVTBL mop_accessor_vtbl = { /* the MAGIC identity */
19 mop_accessor_get_mg(pTHX_ CV* const xsub){
20 return mop_mg_find(aTHX_ (SV*)xsub, &mop_accessor_vtbl, MOPf_DIE_ON_FAIL);
24 mop_install_accessor(pTHX_ const char* const fq_name, const char* const key, I32 const keylen, XSUBADDR_t const accessor_impl, const mop_instance_vtbl* vtbl){
25 CV* const xsub = newXS((char*)fq_name, accessor_impl, __FILE__);
26 SV* const keysv = newSVpvn_share(key, keylen, 0U);
30 vtbl = mop_get_default_instance_vtbl(aTHX);
34 /* generated_xsub need sv_2mortal */
35 sv_2mortal((SV*)xsub);
38 mg = sv_magicext((SV*)xsub, keysv, PERL_MAGIC_ext, &mop_accessor_vtbl, (char*)vtbl, 0);
39 SvREFCNT_dec(keysv); /* sv_magicext() increases refcnt in mg_obj */
42 * although we use MAGIC for gc, we also store mg to CvXSUBANY slot for efficiency (gfx)
44 CvXSUBANY(xsub).any_ptr = (void*)mg;
51 mop_instantiate_xs_accessor(pTHX_ SV* const accessor, XSUBADDR_t const accessor_impl, mop_instance_vtbl* const vtbl){
52 /* $key = $accessor->associated_attribute->name */
53 SV* const attr = mop_call0(aTHX_ accessor, mop_associated_attribute);
54 SV* const key = mop_call0(aTHX_ attr, mop_name);
57 const char* const kpv = SvPV_const(key, klen);
59 MAGIC* mg = mop_attr_get_mg(aTHX_ attr);
61 CV* const xsub = newXS(NULL, accessor_impl, __FILE__);
62 sv_2mortal((SV*)xsub);
64 MOP_mg_obj(mg) = newSVpvn_share(kpv, klen, 0U);
65 MOP_mg_obj_refcounted_on(mg);
67 CvXSUBANY(xsub).any_ptr = sv_magicext((SV*)xsub, MOP_mg_obj(mg), PERL_MAGIC_ext, MOP_mg_virtual(mg), (char*)vtbl, 0);
73 mop_accessor_get_self(pTHX_ I32 const ax, I32 const items, CV* const cv) {
77 croak("too few arguments for %s", GvNAME(CvGV(cv)));
80 /* NOTE: If self has GETMAGIC, $self->accessor will invoke GETMAGIC
81 * before calling methods, so SvGETMAGIC(self) is not necessarily needed here.
85 if(!(SvROK(self) && SvOBJECT(SvRV(self)))){
86 croak("cant call %s as a class method", GvNAME(CvGV(cv)));
91 XS(mop_xs_simple_accessor)
94 dMOP_METHOD_COMMON; /* self, mg */
97 if(items == 1){ /* reader */
98 value = MOP_mg_get_slot(mg, self);
100 else if (items == 2){ /* writer */
101 value = MOP_mg_set_slot(mg, self, ST(1));
104 croak("expected exactly one or two argument");
107 ST(0) = value ? value : &PL_sv_undef;
112 XS(mop_xs_simple_reader)
115 dMOP_METHOD_COMMON; /* self, mg */
119 croak("expected exactly one argument");
122 value = MOP_mg_get_slot(mg, self);
123 ST(0) = value ? value : &PL_sv_undef;
127 XS(mop_xs_simple_writer)
130 dMOP_METHOD_COMMON; /* self, mg */
133 croak("expected exactly two argument");
136 ST(0) = MOP_mg_set_slot(mg, self, ST(1));
140 XS(mop_xs_simple_clearer)
143 dMOP_METHOD_COMMON; /* self, mg */
147 croak("expected exactly one argument");
150 value = MOP_mg_delete_slot(mg, self);
151 ST(0) = value ? value : &PL_sv_undef;
156 XS(mop_xs_simple_predicate)
159 dMOP_METHOD_COMMON; /* self, mg */
162 croak("expected exactly one argument");
165 ST(0) = boolSV( MOP_mg_has_slot(mg, self) );
170 XS(mop_xs_simple_predicate_for_metaclass)
173 dMOP_METHOD_COMMON; /* self, mg */
177 croak("expected exactly one argument");
180 value = MOP_mg_get_slot(mg, self);
181 ST(0) = boolSV( value && SvOK(value ));
185 MODULE = Class::MOP::Method::Accessor PACKAGE = Class::MOP::Method::Accessor
190 INSTALL_SIMPLE_READER_WITH_KEY(Method::Accessor, associated_attribute, attribute);
191 INSTALL_SIMPLE_READER(Method::Accessor, accessor_type);
195 _generate_accessor_method_xs(SV* self, void* instance_vtbl)
197 RETVAL = mop_instantiate_xs_accessor(aTHX_ self, mop_xs_simple_accessor, instance_vtbl);
202 _generate_reader_method_xs(SV* self, void* instance_vtbl)
204 RETVAL = mop_instantiate_xs_accessor(aTHX_ self, mop_xs_simple_reader, instance_vtbl);
209 _generate_writer_method_xs(SV* self, void* instance_vtbl)
211 RETVAL = mop_instantiate_xs_accessor(aTHX_ self, mop_xs_simple_writer, instance_vtbl);
216 _generate_predicate_method_xs(SV* self, void* instance_vtbl)
218 RETVAL = mop_instantiate_xs_accessor(aTHX_ self, mop_xs_simple_predicate, instance_vtbl);
223 _generate_clearer_method_xs(SV* self, void* instance_vtbl)
225 RETVAL = mop_instantiate_xs_accessor(aTHX_ self, mop_xs_simple_clearer, instance_vtbl);