Rebase origin and fix miss-merged segments
[gitmo/Class-MOP.git] / xs / Package.xs
CommitLineData
d846ade3 1#include "mop.h"
2
e2e116c2 3static void
b1ff395f 4mop_update_method_map(pTHX_ SV *const self, SV *const class_name, HV *const stash, HV *const map)
5{
6 const char *const class_name_pv = HvNAME(stash); /* must be HvNAME(stash), not SvPV_nolen_const(class_name) */
7 SV *method_metaclass_name;
8 char *method_name;
9 I32 method_name_len;
10 SV *coderef;
11 HV *symbols;
12 dSP;
13
14 symbols = mop_get_all_package_symbols(stash, TYPE_FILTER_CODE);
15 sv_2mortal((SV*)symbols);
16 (void)hv_iterinit(symbols);
17 while ( (coderef = hv_iternextsv(symbols, &method_name, &method_name_len)) ) {
18 CV *cv = (CV *)SvRV(coderef);
19 char *cvpkg_name;
20 char *cv_name;
21 SV *method_slot;
22 SV *method_object;
23
24 if (!mop_get_code_info(coderef, &cvpkg_name, &cv_name)) {
25 continue;
26 }
27
28 /* this checks to see that the subroutine is actually from our package */
29 if ( !(strEQ(cvpkg_name, "constant") && strEQ(cv_name, "__ANON__")) ) {
30 if ( strNE(cvpkg_name, class_name_pv) ) {
31 continue;
32 }
33 }
34
35 method_slot = *hv_fetch(map, method_name, method_name_len, TRUE);
36 if ( SvOK(method_slot) ) {
daf9799b 37 SV *const body = mop_call0(aTHX_ method_slot, mop_body); /* $method_object->body() */
b1ff395f 38 if ( SvROK(body) && ((CV *) SvRV(body)) == cv ) {
39 continue;
40 }
41 }
42
43 method_metaclass_name = mop_call0(aTHX_ self, mop_method_metaclass); /* $self->method_metaclass() */
44
45 /*
46 $method_object = $method_metaclass->wrap(
47 $cv,
48 associated_metaclass => $self,
49 package_name => $class_name,
50 name => $method_name
51 );
52 */
53 ENTER;
54 SAVETMPS;
55
56 PUSHMARK(SP);
57 EXTEND(SP, 8);
58 PUSHs(method_metaclass_name); /* invocant */
59 mPUSHs(newRV_inc((SV *)cv));
60 PUSHs(mop_associated_metaclass);
61 PUSHs(self);
daf9799b 62 PUSHs(mop_package_name);
b1ff395f 63 PUSHs(class_name);
daf9799b 64 PUSHs(mop_name);
b1ff395f 65 mPUSHs(newSVpv(method_name, method_name_len));
66 PUTBACK;
67
68 call_sv(mop_wrap, G_SCALAR | G_METHOD);
69 SPAGAIN;
70 method_object = POPs;
71 PUTBACK;
72 /* $map->{$method_name} = $method_object */
73 sv_setsv(method_slot, method_object);
74
75 FREETMPS;
76 LEAVE;
77 }
78}
79
d846ade3 80MODULE = Class::MOP::Package PACKAGE = Class::MOP::Package
81
82PROTOTYPES: DISABLE
83
b66ddbab 84VERSIONCHECK: DISABLE
85
b97582b7 86BOOT:
87 INSTALL_SIMPLE_READER_WITH_KEY(Package, name, package);
88 INSTALL_SIMPLE_READER_WITH_KEY(Package, _method_map, methods);
89 INSTALL_SIMPLE_READER(Package, method_metaclass);
90 INSTALL_SIMPLE_READER(Package, wrapped_method_metaclass);
91
d846ade3 92void
93get_all_package_symbols(self, filter=TYPE_FILTER_NONE)
94 SV *self
95 type_filter_t filter
96 PREINIT:
97 HV *stash = NULL;
98 HV *symbols = NULL;
99 register HE *he;
100 PPCODE:
101 if ( ! SvROK(self) ) {
102 die("Cannot call get_all_package_symbols as a class method");
103 }
104
105 if (GIMME_V == G_VOID) {
106 XSRETURN_EMPTY;
107 }
108
109 PUTBACK;
110
1bc0cb6b 111 if ( (he = hv_fetch_ent((HV *)SvRV(self), mop_package, 0, 0U)) ) {
d846ade3 112 stash = gv_stashsv(HeVAL(he), 0);
113 }
114
115
116 if (!stash) {
117 XSRETURN_UNDEF;
118 }
119
e1f52a8a 120 symbols = mop_get_all_package_symbols(stash, filter);
d846ade3 121 PUSHs(sv_2mortal(newRV_noinc((SV *)symbols)));
122
b1ff395f 123void
124get_method_map(self)
125 SV *self
126 PREINIT:
127 HV *const obj = (HV *)SvRV(self);
daf9799b 128 SV *const class_name = HeVAL( hv_fetch_ent(obj, mop_package, 0, 0U) );
b1ff395f 129 HV *const stash = gv_stashsv(class_name, 0);
130 UV current;
131 SV *cache_flag;
132 SV *map_ref;
133 PPCODE:
134 if (!stash) {
135 mXPUSHs(newRV_noinc((SV *)newHV()));
136 return;
137 }
138
139 current = mop_check_package_cache_flag(aTHX_ stash);
daf9799b 140 cache_flag = HeVAL( hv_fetch_ent(obj, mop_package_cache_flag, TRUE, 0U));
141 map_ref = HeVAL( hv_fetch_ent(obj, mop_methods, TRUE, 0U));
b1ff395f 142
143 /* $self->{methods} does not yet exist (or got deleted) */
144 if ( !SvROK(map_ref) || SvTYPE(SvRV(map_ref)) != SVt_PVHV ) {
145 SV *new_map_ref = newRV_noinc((SV *)newHV());
146 sv_2mortal(new_map_ref);
147 sv_setsv(map_ref, new_map_ref);
148 }
149
150 if ( !SvOK(cache_flag) || SvUV(cache_flag) != current ) {
151 mop_update_method_map(aTHX_ self, class_name, stash, (HV *)SvRV(map_ref));
152 sv_setuv(cache_flag, mop_check_package_cache_flag(aTHX_ stash)); /* update_cache_flag() */
153 }
154
155 XPUSHs(map_ref);