1 #define NEED_newSVpvn_flags_GLOBAL
9 static SV* mouse_all_attrs_cache;
10 static SV* mouse_all_attrs_cache_gen;
13 mouse_get_all_attributes(pTHX_ SV* const metaclass){
14 SV* const package = get_slot(metaclass, mouse_package);
15 HV* const stash = gv_stashsv(package, TRUE);
16 UV const pkg_gen = mro_get_pkg_gen(stash);
17 SV* cache_gen = get_slot(metaclass, mouse_all_attrs_cache_gen);
19 if(!(cache_gen && pkg_gen == SvUV(cache_gen))){ /* update */
20 CV* const get_metaclass = get_cvs("Mouse::Util::get_metaclass_by_name", TRUE);
21 AV* const linearized_isa = mro_get_linear_isa(stash);
22 I32 const len = AvFILLp(linearized_isa);
25 AV* const all_attrs = newAV();
27 /* warn("Update all_attrs_cache (cache_gen %d != pkg_gen %d)", (cache_gen ? (int)SvIV(cache_gen) : 0), (int)pkg_gen); //*/
32 set_slot(metaclass, mouse_all_attrs_cache, sv_2mortal(newRV_inc((SV*)all_attrs)));
35 sv_2mortal((SV*)seen);
37 for(i = 0; i < len; i++){
38 SV* const klass = MOUSE_av_at(linearized_isa, i);
47 call_sv((SV*)get_metaclass, G_SCALAR);
54 continue; /* skip non-Mouse classes */
57 /* $meta->get_attribute_list */
62 n = call_method("get_attribute_list", G_ARRAY);
63 for(NOOP; n > 0; n--){
70 if(hv_exists_ent(seen, name, 0U)){
73 (void)hv_store_ent(seen, name, &PL_sv_undef, 0U);
75 av_push(all_attrs, newSVsv( mcall1s(meta, "get_attribute", name) ));
80 cache_gen = sv_newmortal();
82 sv_setuv(cache_gen, mro_get_pkg_gen(stash));
83 set_slot(metaclass, mouse_all_attrs_cache_gen, cache_gen);
91 SV* const all_attrs_ref = get_slot(metaclass, mouse_all_attrs_cache);
93 if(!IsArrayRef(all_attrs_ref)){
94 croak("Not an ARRAY reference");
97 return (AV*)SvRV(all_attrs_ref);
101 MODULE = Mouse PACKAGE = Mouse
106 mouse_package = newSVpvs_share("package");
107 mouse_namespace = newSVpvs_share("namespace");
108 mouse_methods = newSVpvs_share("methods");
109 mouse_name = newSVpvs_share("name");
111 mouse_all_attrs_cache = newSVpvs_share("__all_attrs_cache");
112 mouse_all_attrs_cache_gen = newSVpvs_share("__all_attrs_cache_gen");
114 MOUSE_CALL_BOOT(Mouse__Util);
115 MOUSE_CALL_BOOT(Mouse__Util__TypeConstraints);
116 MOUSE_CALL_BOOT(Mouse__Meta__Method__Accessor__XS);
119 MODULE = Mouse PACKAGE = Mouse::Meta::Module
122 INSTALL_SIMPLE_READER_WITH_KEY(Module, name, package);
123 INSTALL_SIMPLE_READER_WITH_KEY(Module, _method_map, methods);
124 INSTALL_SIMPLE_READER_WITH_KEY(Module, _attribute_map, attributes);
130 SV* const package = get_slot(self, mouse_package);
131 if(!(package && SvOK(package))){
132 croak("No package name defined");
134 RETVAL = gv_stashsv(package, GV_ADDMULTI);
139 # ignore extra arguments for extensibility
141 add_method(SV* self, SV* name, SV* code, ...)
144 SV* const package = get_slot(self, mouse_package); /* $self->{package} */
145 SV* const methods = get_slot(self, mouse_methods); /* $self->{methods} */
149 if(!(package && SvOK(package))){
150 croak("No package name defined");
157 mouse_throw_error(self, NULL, "You must define a method name");
160 mouse_throw_error(self, NULL, "You must define a CODE reference");
164 if(SvTYPE(SvRV(code_ref)) != SVt_PVCV){
165 SV* sv = code_ref; /* used in tryAMAGICunDEREF */
166 SV** sp = &sv; /* used in tryAMAGICunDEREF */
167 tryAMAGICunDEREF(to_cv); /* try \&{$code} */
168 if(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV){
169 mouse_throw_error(self, NULL, "Not a CODE reference");
174 /* *{$package . '::' . $name} -> *gv */
175 gv = gv_fetchpv(form("%"SVf"::%"SVf, package, name), GV_ADDMULTI, SVt_PVCV);
176 if(GvCVu(gv)){ /* delete *slot{gv} to work around "redefine" warning */
177 SvREFCNT_dec(GvCV(gv));
180 sv_setsv_mg((SV*)gv, code_ref); /* *gv = $code_ref */
182 set_slot(methods, name, code); /* $self->{methods}{$name} = $code */
184 /* TODO: name the CODE ref if it's anonymous */
185 //code_entity = (CV*)SvRV(code_ref);
186 //if(CvANON(code_entity)
187 // && CvGV(code_entity) /* a cv under construction has no gv */ ){
189 // CvGV(code_entity) = gv;
190 // CvANON_off(code_entity);
194 MODULE = Mouse PACKAGE = Mouse::Meta::Class
197 INSTALL_SIMPLE_READER(Class, roles);
198 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id);
201 linearized_isa(SV* self)
204 SV* const stash_ref = mcall0(self, mouse_namespace); /* $self->namespace */
208 if(!(SvROK(stash_ref) && SvTYPE(SvRV(stash_ref)) == SVt_PVHV)){
209 croak("namespace() didn't return a HASH reference");
211 linearized_isa = mro_get_linear_isa((HV*)SvRV(stash_ref));
212 len = AvFILLp(linearized_isa) + 1;
214 for(i = 0; i < len; i++){
215 PUSHs(AvARRAY(linearized_isa)[i]);
220 get_all_attributes(SV* self)
223 AV* const all_attrs = mouse_get_all_attributes(aTHX_ self);
224 I32 const len = AvFILLp(all_attrs) + 1;
228 for(i = 0; i < len; i++){
229 PUSHs( MOUSE_av_at(all_attrs, i) );
233 MODULE = Mouse PACKAGE = Mouse::Meta::Role
236 INSTALL_SIMPLE_READER_WITH_KEY(Role, get_roles, roles);
237 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Role, is_anon_role, anon_serial_id);
239 MODULE = Mouse PACKAGE = Mouse::Meta::Attribute
243 INSTALL_SIMPLE_READER(Attribute, name);
244 INSTALL_SIMPLE_READER(Attribute, associated_class);
245 INSTALL_SIMPLE_READER(Attribute, accessor);
246 INSTALL_SIMPLE_READER(Attribute, reader);
247 INSTALL_SIMPLE_READER(Attribute, writer);
248 INSTALL_SIMPLE_READER(Attribute, predicate);
249 INSTALL_SIMPLE_READER(Attribute, clearer);
250 INSTALL_SIMPLE_READER(Attribute, handles);
252 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, _is_metadata, is);
253 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_required, required);
254 INSTALL_SIMPLE_READER(Attribute, default);
255 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy, lazy);
256 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy_build, lazy_build);
257 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_weak_ref, weak_ref);
258 INSTALL_SIMPLE_READER(Attribute, init_arg);
259 INSTALL_SIMPLE_READER(Attribute, type_constraint);
260 INSTALL_SIMPLE_READER(Attribute, trigger);
261 INSTALL_SIMPLE_READER(Attribute, builder);
262 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_auto_deref, auto_deref);
263 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_coerce, coerce);
264 INSTALL_SIMPLE_READER(Attribute, documentation);
267 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_accessor, accessor);
268 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_reader, reader);
269 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_writer, writer);
270 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_predicate, predicate);
271 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_clearer, clearer);
272 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_handles, handles);
274 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_default, default);
275 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_type_constraint, type_constraint);
276 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_trigger, trigger);
277 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_builder, builder);
278 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_documentation, documentation);
280 newCONSTSUB(gv_stashpvs("Mouse::Meta::Attribute", TRUE), "accessor_metaclass",
281 newSVpvs("Mouse::Meta::Method::Accessor::XS"));