5 mop_deconstruct_variable_name(pTHX_ SV* const variable,
6 const char** const var_name, STRLEN* const var_name_len,
8 const char** const type_name) {
11 if(SvROK(variable) && SvTYPE(SvRV(variable)) == SVt_PVHV){
12 /* e.g. variable = { type => "SCALAR", name => "foo" } */
13 HV* const hv = (HV*)SvRV(variable);
18 svp = hv_fetchs(hv, "name", FALSE);
19 if(!(svp && SvOK(*svp))){
20 croak("You must pass a variable name");
22 *var_name = SvPV_const(*svp, len);
25 croak("You must pass a variable name");
28 svp = hv_fetchs(hv, "type", FALSE);
29 if(!(svp && SvOK(*svp))) {
30 croak("You must pass a variable type");
32 pv = SvPV_nolen_const(*svp);
33 if(strEQ(pv, "SCALAR")){
34 *type = SVt_PV; /* for all the type of scalars */
36 else if(strEQ(pv, "ARRAY")){
39 else if(strEQ(pv, "HASH")){
42 else if(strEQ(pv, "CODE")){
45 else if(strEQ(pv, "GLOB")){
48 else if(strEQ(pv, "IO")){
52 croak("I do not recognize that type '%s'", pv);
59 /* e.g. variable = '$foo' */
61 croak("You must pass a variable name");
63 pv = SvPV_const(variable, len);
65 croak("You must pass a variable name including a sigil");
69 *var_name_len = len - 1;
73 *type = SVt_PV; /* for all the types of scalars */
74 *type_name = "SCALAR";
93 croak("I do not recognize that sigil '%c'", pv[0]);
99 mop_get_gv(pTHX_ SV* const self, svtype const type, const char* const var_name, I32 const var_name_len, I32 const flags){
102 if(!(flags & ~GV_NOADD_MASK)){ /* for shortcut fetching */
103 SV* const ns = mop_call0(aTHX_ self, mop_namespace);
105 if(!(SvROK(ns) && SvTYPE(SvRV(ns)) == SVt_PVHV)){
106 croak("namespace() did not return a hash reference");
108 gvp = (GV**)hv_fetch((HV*)SvRV(ns), var_name, var_name_len, FALSE);
109 if(gvp && isGV_with_GP(*gvp)){
114 package_name = mop_call0(aTHX_ self, KEY_FOR(name));
116 if(!SvOK(package_name)){
117 croak("name() did not return a defined value");
120 return gv_fetchpv(Perl_form(aTHX_ "%"SVf"::%s", package_name, var_name), flags, type);
124 mop_gv_elem(pTHX_ GV* const gv, svtype const type, I32 const add){
131 assert(isGV_with_GP(gv));
135 sv = (SV*)(add ? GvAVn(gv) : GvAV(gv));
138 sv = (SV*)(add ? GvHVn(gv) : GvHV(gv));
144 sv = (SV*)(add ? GvIOn(gv) : GvIO(gv));
149 default: /* SCALAR */
150 sv = add ? GvSVn(gv) : GvSV(gv);
159 mop_update_method_map(pTHX_ SV *const self, SV *const class_name, HV *const stash, HV *const map)
161 const char *const class_name_pv = HvNAME(stash); /* must be HvNAME(stash), not SvPV_nolen_const(class_name) */
162 SV *method_metaclass_name;
169 symbols = mop_get_all_package_symbols(stash, TYPE_FILTER_CODE);
170 sv_2mortal((SV*)symbols);
171 (void)hv_iterinit(symbols);
172 while ( (coderef = hv_iternextsv(symbols, &method_name, &method_name_len)) ) {
173 CV *cv = (CV *)SvRV(coderef);
179 if (!mop_get_code_info(coderef, &cvpkg_name, &cv_name)) {
183 /* this checks to see that the subroutine is actually from our package */
184 if ( !(strEQ(cvpkg_name, "constant") && strEQ(cv_name, "__ANON__")) ) {
185 if ( strNE(cvpkg_name, class_name_pv) ) {
190 method_slot = *hv_fetch(map, method_name, method_name_len, TRUE);
191 if ( SvOK(method_slot) ) {
192 SV *const body = mop_call0(aTHX_ method_slot, KEY_FOR(body)); /* $method_object->body() */
193 if ( SvROK(body) && ((CV *) SvRV(body)) == cv ) {
198 method_metaclass_name = mop_call0(aTHX_ self, mop_method_metaclass); /* $self->method_metaclass() */
201 $method_object = $method_metaclass->wrap(
203 associated_metaclass => $self,
204 package_name => $class_name,
213 PUSHs(method_metaclass_name); /* invocant */
214 mPUSHs(newRV_inc((SV *)cv));
215 PUSHs(mop_associated_metaclass);
217 PUSHs(KEY_FOR(package_name));
219 PUSHs(KEY_FOR(name));
220 mPUSHs(newSVpv(method_name, method_name_len));
223 call_sv(mop_wrap, G_SCALAR | G_METHOD);
225 method_object = POPs;
227 /* $map->{$method_name} = $method_object */
228 sv_setsv(method_slot, method_object);
235 MODULE = Class::MOP::Package PACKAGE = Class::MOP::Package
240 get_all_package_symbols(self, filter=TYPE_FILTER_NONE)
248 if ( ! SvROK(self) ) {
249 die("Cannot call get_all_package_symbols as a class method");
252 if (GIMME_V == G_VOID) {
258 if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(package), 0, HASH_FOR(package))) ) {
259 stash = gv_stashsv(HeVAL(he), 0);
267 symbols = mop_get_all_package_symbols(stash, filter);
268 PUSHs(sv_2mortal(newRV_noinc((SV *)symbols)));
274 HV *const obj = (HV *)SvRV(self);
275 SV *const class_name = HeVAL( hv_fetch_ent(obj, KEY_FOR(package), 0, HASH_FOR(package)) );
276 HV *const stash = gv_stashsv(class_name, 0);
282 mXPUSHs(newRV_noinc((SV *)newHV()));
286 current = mop_check_package_cache_flag(aTHX_ stash);
287 cache_flag = HeVAL( hv_fetch_ent(obj, KEY_FOR(package_cache_flag), TRUE, HASH_FOR(package_cache_flag)));
288 map_ref = HeVAL( hv_fetch_ent(obj, KEY_FOR(methods), TRUE, HASH_FOR(methods)));
290 /* $self->{methods} does not yet exist (or got deleted) */
291 if ( !SvROK(map_ref) || SvTYPE(SvRV(map_ref)) != SVt_PVHV ) {
292 SV *new_map_ref = newRV_noinc((SV *)newHV());
293 sv_2mortal(new_map_ref);
294 sv_setsv(map_ref, new_map_ref);
297 if ( !SvOK(cache_flag) || SvUV(cache_flag) != current ) {
298 mop_update_method_map(aTHX_ self, class_name, stash, (HV *)SvRV(map_ref));
299 sv_setuv(cache_flag, mop_check_package_cache_flag(aTHX_ stash)); /* update_cache_flag() */
305 INSTALL_SIMPLE_READER_WITH_KEY(Package, name, package);
309 add_package_symbol(SV* self, SV* variable, SV* ref = &PL_sv_undef)
312 const char* type_name;
313 const char* var_name;
317 mop_deconstruct_variable_name(aTHX_ variable, &var_name, &var_name_len, &type, &type_name);
318 gv = mop_get_gv(aTHX_ self, type, var_name, var_name_len, GV_ADDMULTI);
320 if(SvOK(ref)){ /* add_package_symbol with a value */
323 ref = newRV_noinc(newSVsv(ref));
327 else if(!(SvROK(ref) && SvTYPE(SvRV(ref)) == type)){
328 croak("You must pass a reference of %s for the value of %s", type_name, GvNAME(CvGV(cv)));
331 if(type == SVt_PVCV && GvCV(gv)){
332 /* XXX: clear it before redefinition */
333 SvREFCNT_dec(GvCV(gv));
336 sv_setsv_mg((SV*)gv, ref); /* magical assignment into type glob (*glob = $ref) */
338 if(type == SVt_PVCV){ /* name a subroutine */
339 CV* const subr = (CV*)SvRV(ref);
343 && strEQ(GvNAME(CvGV(subr)), "__ANON__")){
350 SvREFCNT_inc_simple_void_NN(ref);
353 SV* const sv = mop_gv_elem(aTHX_ gv, type, GV_ADDMULTI);
354 RETVAL = (sv && GIMME_V != G_VOID) ? newRV_inc(sv) : &PL_sv_undef;
360 has_package_symbol(SV* self, SV* variable)
363 const char* type_name;
364 const char* var_name;
368 mop_deconstruct_variable_name(aTHX_ variable, &var_name, &var_name_len, &type, &type_name);
369 gv = mop_get_gv(aTHX_ self, type, var_name, var_name_len, 0);
370 RETVAL = mop_gv_elem(aTHX_ gv, type, FALSE) ? TRUE : FALSE;
375 get_package_symbol(SV* self, SV* variable, ...)
378 const char* type_name;
379 const char* var_name;
385 { /* parse options */
387 if((items % 2) != 0){
388 croak("Odd number of arguments for get_package_symbol()");
390 for(i = 2; i < items; i += 2){
391 SV* const opt = ST(i);
392 SV* const val = ST(i+1);
393 if(strEQ(SvPV_nolen_const(opt), "create")){
395 flags |= GV_ADDMULTI;
398 flags &= ~GV_ADDMULTI;
402 warn("Unknown option \"%"SVf"\" for get_package_symbol()", opt);
406 mop_deconstruct_variable_name(aTHX_ variable, &var_name, &var_name_len, &type, &type_name);
407 gv = mop_get_gv(aTHX_ self, type, var_name, var_name_len, flags);
408 sv = mop_gv_elem(aTHX_ gv, type, FALSE);
410 RETVAL = sv ? newRV_inc(sv) : &PL_sv_undef;