static void
mop_update_method_map(pTHX_ SV *const self, SV *const class_name, HV *const stash, HV *const map)
{
- const char *const class_name_pv = HvNAME(stash); /* must be HvNAME(stash), not SvPV_nolen_const(class_name) */
- SV *method_metaclass_name;
char *method_name;
I32 method_name_len;
- SV *coderef;
+ SV *method;
HV *symbols;
- dSP;
symbols = mop_get_all_package_symbols(stash, TYPE_FILTER_CODE);
sv_2mortal((SV*)symbols);
- (void)hv_iterinit(symbols);
- while ( (coderef = hv_iternextsv(symbols, &method_name, &method_name_len)) ) {
- CV *cv = (CV *)SvRV(coderef);
- char *cvpkg_name;
- char *cv_name;
- SV *method_slot;
- SV *method_object;
-
- if (!mop_get_code_info(coderef, &cvpkg_name, &cv_name)) {
+
+ (void)hv_iterinit(map);
+ while ((method = hv_iternextsv(map, &method_name, &method_name_len))) {
+ SV *body;
+ SV *stash_slot;
+
+ if (!SvROK(method)) {
continue;
}
- /* this checks to see that the subroutine is actually from our package */
- if ( !(strEQ(cvpkg_name, "constant") && strEQ(cv_name, "__ANON__")) ) {
- if ( strNE(cvpkg_name, class_name_pv) ) {
- continue;
- }
+ if (sv_isobject(method)) {
+ /* $method_object->body() */
+ body = mop_call0(aTHX_ method, KEY_FOR(body));
+ }
+ else {
+ body = method;
}
- method_slot = *hv_fetch(map, method_name, method_name_len, TRUE);
- if ( SvOK(method_slot) ) {
- SV *body;
-
- if ( sv_isobject(method_slot) ) {
- body = mop_call0(aTHX_ method_slot, KEY_FOR(body)); /* $method_object->body() */
- }
- else {
- body = method_slot;
- }
-
- if ( SvROK(body) && ((CV *) SvRV(body)) == cv ) {
- continue;
- }
+ stash_slot = *hv_fetch(symbols, method_name, method_name_len, TRUE);
+ if (SvROK(stash_slot) && ((CV*)SvRV(body)) == ((CV*)SvRV(stash_slot))) {
+ continue;
}
- method_metaclass_name = mop_call0(aTHX_ self, mop_method_metaclass); /* $self->method_metaclass() */
-
- /*
- $method_object = $method_metaclass->wrap(
- $cv,
- associated_metaclass => $self,
- package_name => $class_name,
- name => $method_name
- );
- */
- ENTER;
- SAVETMPS;
-
- PUSHMARK(SP);
- EXTEND(SP, 8);
- PUSHs(method_metaclass_name); /* invocant */
- mPUSHs(newRV_inc((SV *)cv));
- PUSHs(mop_associated_metaclass);
- PUSHs(self);
- PUSHs(KEY_FOR(package_name));
- PUSHs(class_name);
- PUSHs(KEY_FOR(name));
- mPUSHs(newSVpv(method_name, method_name_len));
- PUTBACK;
-
- call_sv(mop_wrap, G_SCALAR | G_METHOD);
- SPAGAIN;
- method_object = POPs;
- PUTBACK;
- /* $map->{$method_name} = $method_object */
- sv_setsv(method_slot, method_object);
-
- FREETMPS;
- LEAVE;
+ /* $map->{$method_name} = undef */
+ sv_setsv(method, &PL_sv_undef);
}
}
PROTOTYPES: DISABLE
void
-_full_method_map(self)
+_method_map(self)
SV *self
PREINIT:
HV *const obj = (HV *)SvRV(self);
mop_method_metaclass = newSVpvs("method_metaclass");
mop_associated_metaclass = newSVpvs("associated_metaclass");
mop_wrap = newSVpvs("wrap");
+ INSTALL_SIMPLE_READER(Mixin::HasMethods, method_metaclass);
+ INSTALL_SIMPLE_READER(Mixin::HasMethods, wrapped_method_metaclass);