}
for(i = 0; i < len; i++){
- SV* const attr = AvARRAY(attrs)[i];
- AV* const xa = mouse_get_xa(aTHX_ AvARRAY(attrs)[i]);
+ SV* const attr = MOUSE_av_at(attrs, i);
+ AV* const xa = mouse_get_xa(aTHX_ attr);
SV* const slot = MOUSE_xa_slot(xa);
U16 const flags = (U16)MOUSE_xa_flags(xa);
return meta;
}
+
+/* copied from Class-MOP/topic/symbol-manipluator */
+static GV*
+mouse_get_gv(pTHX_ SV* const self, svtype const type, const char* const var_name, I32 const var_name_len, I32 const flags){
+ SV* package_name;
+ STRLEN len;
+ const char* pv;
+
+ if(!flags){
+ SV* const ns = mcall0(self, mouse_namespace);
+ GV** gvp;
+ if(!(SvROK(ns) && SvTYPE(SvRV(ns)) == SVt_PVHV)){
+ croak("namespace() did not return a hash reference");
+ }
+ gvp = (GV**)hv_fetch((HV*)SvRV(ns), var_name, var_name_len, FALSE);
+ if(gvp && isGV_with_GP(*gvp)){
+ return *gvp;
+ }
+ }
+
+ package_name = get_slot(self, mouse_package);
+
+ if(!(package_name && SvOK(package_name))){
+ croak("No package name defined");
+ }
+
+ pv = SvPV_const(package_name, len);
+
+ return gv_fetchpvn_flags(Perl_form(aTHX_ "%s::%s", pv, var_name), (len + var_name_len + 2), flags, type);
+}
+
+/* copied from Class-MOP/topic/symbol-manipluator */
+static SV*
+mouse_gv_elem(pTHX_ GV* const gv, svtype const type, I32 const add){
+ SV* sv;
+
+ if(!gv){
+ return NULL;
+ }
+
+ assert(isGV_with_GP(gv));
+
+ switch(type){
+ case SVt_PVAV:
+ sv = (SV*)(add ? GvAVn(gv) : GvAV(gv));
+ break;
+ case SVt_PVHV:
+ sv = (SV*)(add ? GvHVn(gv) : GvHV(gv));
+ break;
+ case SVt_PVCV:
+ sv = (SV*)GvCV(gv);
+ break;
+ case SVt_PVIO:
+ sv = (SV*)(add ? GvIOn(gv) : GvIO(gv));
+ break;
+ case SVt_PVGV:
+ sv = (SV*)gv;
+ break;
+ default: /* SCALAR */
+ sv = add ? GvSVn(gv) : GvSV(gv);
+ break;
+ }
+
+ return sv;
+}
+
+/* copied from Class-MOP/topic/symbol-manipluator */
+static void
+mouse_deconstruct_variable_name(pTHX_ SV* const variable,
+ const char** const var_name, STRLEN* const var_name_len,
+ svtype* const type,
+ const char** const type_name) {
+
+ STRLEN len;
+ const char* pv;
+
+ /* e.g. variable = '$foo' */
+
+ if(!SvOK(variable)) {
+ croak("You must pass a variable name");
+ }
+ pv = SvPV_const(variable, len);
+ if(len < 2){
+ croak("You must pass a variable name including a sigil");
+ }
+
+ *var_name = pv + 1;
+ *var_name_len = len - 1;
+
+ switch(pv[0]){
+ case '$':
+ *type = SVt_PV; /* for all the types of scalars */
+ *type_name = "SCALAR";
+ break;
+ case '@':
+ *type = SVt_PVAV;
+ *type_name = "ARRAY";
+ break;
+ case '%':
+ *type = SVt_PVHV;
+ *type_name = "HASH";
+ break;
+ case '&':
+ *type = SVt_PVCV;
+ *type_name = "CODE";
+ break;
+ case '*':
+ *type = SVt_PVGV;
+ *type_name = "GLOB";
+ break;
+ default:
+ croak("I do not recognize that sigil '%c'", pv[0]);
+ }
+}
+
+
MODULE = Mouse PACKAGE = Mouse
PROTOTYPES: DISABLE
SV* sv = code_ref; /* used in tryAMAGICunDEREF */
SV** sp = &sv; /* used in tryAMAGICunDEREF */
tryAMAGICunDEREF(to_cv); /* try \&{$code} */
- if(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV){
- mouse_throw_error(self, NULL, "Not a CODE reference");
+ if(!(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV)){
+ mouse_throw_error(self, NULL, "You must pass a CODE reference to add_method");
}
code_ref = sv;
}
}
}
+bool
+has_package_symbol(SV* self, SV* variable)
+PREINIT:
+ svtype type;
+ const char* type_name;
+ const char* var_name;
+ STRLEN var_name_len;
+ GV* gv;
+CODE:
+ mouse_deconstruct_variable_name(aTHX_ variable, &var_name, &var_name_len, &type, &type_name);
+ gv = mouse_get_gv(aTHX_ self, type, var_name, var_name_len, 0);
+ RETVAL = mouse_gv_elem(aTHX_ gv, type, FALSE) ? TRUE : FALSE;
+OUTPUT:
+ RETVAL
+
+SV*
+get_package_symbol(SV* self, SV* variable)
+PREINIT:
+ svtype type;
+ const char* type_name;
+ const char* var_name;
+ STRLEN var_name_len;
+ I32 flags = 0;
+ GV* gv;
+ SV* sv;
+CODE:
+ mouse_deconstruct_variable_name(aTHX_ variable, &var_name, &var_name_len, &type, &type_name);
+ gv = mouse_get_gv(aTHX_ self, type, var_name, var_name_len, flags);
+ sv = mouse_gv_elem(aTHX_ gv, type, FALSE);
+
+ RETVAL = sv ? newRV_inc(sv) : &PL_sv_undef;
+OUTPUT:
+ RETVAL
+
+
MODULE = Mouse PACKAGE = Mouse::Meta::Class
BOOT:
INSTALL_SIMPLE_READER(Class, roles);
INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id);
- INSTALL_SIMPLE_ACCESSOR_WITH_DEFAULTS(Class, method_metaclass, "Mouse::Meta::Method");
- INSTALL_SIMPLE_ACCESSOR_WITH_DEFAULTS(Class, attribute_metaclass, "Mouse::Meta::Attribute");
- INSTALL_SIMPLE_ACCESSOR_WITH_DEFAULTS(Class, constructor_class, "Mouse::Meta::Method::Constructor::XS");
- INSTALL_SIMPLE_ACCESSOR_WITH_DEFAULTS(Class, destructor_class, "Mouse::Meta::Method::Destructor::XS");
+ INSTALL_SIMPLE_READER_WITH_DEFAULTS(Class, method_metaclass, "Mouse::Meta::Method");
+ INSTALL_SIMPLE_READER_WITH_DEFAULTS(Class, attribute_metaclass, "Mouse::Meta::Attribute");
+ INSTALL_SIMPLE_READER_WITH_DEFAULTS(Class, constructor_class, "Mouse::Meta::Method::Constructor::XS");
+ INSTALL_SIMPLE_READER_WITH_DEFAULTS(Class, destructor_class, "Mouse::Meta::Method::Destructor::XS");
newCONSTSUB(gv_stashpvs("Mouse::Meta::Method::Constructor::XS", TRUE), "_generate_constructor",
newRV_inc((SV*)get_cvs("Mouse::Object::new", TRUE)));
INSTALL_SIMPLE_READER_WITH_KEY(Role, get_roles, roles);
INSTALL_SIMPLE_PREDICATE_WITH_KEY(Role, is_anon_role, anon_serial_id);
- INSTALL_SIMPLE_ACCESSOR_WITH_DEFAULTS(Role, method_metaclass, "Mouse::Meta::Role::Method");
+ INSTALL_SIMPLE_READER_WITH_DEFAULTS(Role, method_metaclass, "Mouse::Meta::Role::Method");
MODULE = Mouse PACKAGE = Mouse::Object
PUSHMARK(SP);
EXTEND(SP, 2);
- PUSHs(RETVAL);
+ PUSHs(RETVAL); /* self */
PUSHs(args);
PUTBACK;