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 all_attrs = newAV();
22 SV* const get_attribute = newSVpvs_share("get_attribute");
24 AV* const linearized_isa = mro_get_linear_isa(stash);
25 I32 const len = AvFILLp(linearized_isa);
29 /* warn("Update all_attrs_cache (cache_gen %d != pkg_gen %d)", (cache_gen ? (int)SvIV(cache_gen) : 0), (int)pkg_gen); //*/
34 sv_2mortal(get_attribute);
36 set_slot(metaclass, mouse_all_attrs_cache, sv_2mortal(newRV_inc((SV*)all_attrs)));
39 sv_2mortal((SV*)seen);
41 for(i = 0; i < len; i++){
42 SV* const klass = MOUSE_av_at(linearized_isa, i);
51 call_sv((SV*)get_metaclass, G_SCALAR);
58 continue; /* skip non-Mouse classes */
61 /* $meta->get_attribute_list */
66 n = call_method("get_attribute_list", G_ARRAY);
67 for(NOOP; n > 0; n--){
74 if(hv_exists_ent(seen, name, 0U)){
77 (void)hv_store_ent(seen, name, &PL_sv_undef, 0U);
79 av_push(all_attrs, newSVsv( mcall1(meta, get_attribute, name) ));
84 cache_gen = sv_newmortal();
86 sv_setuv(cache_gen, mro_get_pkg_gen(stash));
87 set_slot(metaclass, mouse_all_attrs_cache_gen, cache_gen);
95 SV* const all_attrs_ref = get_slot(metaclass, mouse_all_attrs_cache);
97 if(!IsArrayRef(all_attrs_ref)){
98 croak("Not an ARRAY reference");
101 return (AV*)SvRV(all_attrs_ref);
105 MODULE = Mouse PACKAGE = Mouse
110 mouse_package = newSVpvs_share("package");
111 mouse_namespace = newSVpvs_share("namespace");
112 mouse_methods = newSVpvs_share("methods");
113 mouse_name = newSVpvs_share("name");
115 mouse_all_attrs_cache = newSVpvs_share("__all_attrs_cache");
116 mouse_all_attrs_cache_gen = newSVpvs_share("__all_attrs_cache_gen");
118 MOUSE_CALL_BOOT(Mouse__Util);
119 MOUSE_CALL_BOOT(Mouse__Util__TypeConstraints);
120 MOUSE_CALL_BOOT(Mouse__Meta__Method__Accessor__XS);
123 MODULE = Mouse PACKAGE = Mouse::Meta::Module
126 INSTALL_SIMPLE_READER_WITH_KEY(Module, name, package);
127 INSTALL_SIMPLE_READER_WITH_KEY(Module, _method_map, methods);
128 INSTALL_SIMPLE_READER_WITH_KEY(Module, _attribute_map, attributes);
134 SV* const package = get_slot(self, mouse_package);
135 if(!(package && SvOK(package))){
136 croak("No package name defined");
138 RETVAL = gv_stashsv(package, GV_ADDMULTI);
143 # ignore extra arguments for extensibility
145 add_method(SV* self, SV* name, SV* code, ...)
148 SV* const package = get_slot(self, mouse_package); /* $self->{package} */
149 SV* const methods = get_slot(self, mouse_methods); /* $self->{methods} */
153 if(!(package && SvOK(package))){
154 croak("No package name defined");
161 mouse_throw_error(self, NULL, "You must define a method name");
164 mouse_throw_error(self, NULL, "You must define a CODE reference");
168 if(SvTYPE(SvRV(code_ref)) != SVt_PVCV){
169 SV* sv = code_ref; /* used in tryAMAGICunDEREF */
170 SV** sp = &sv; /* used in tryAMAGICunDEREF */
171 tryAMAGICunDEREF(to_cv); /* try \&{$code} */
172 if(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV){
173 mouse_throw_error(self, NULL, "Not a CODE reference");
178 /* *{$package . '::' . $name} -> *gv */
179 gv = gv_fetchpv(form("%"SVf"::%"SVf, package, name), GV_ADDMULTI, SVt_PVCV);
180 if(GvCVu(gv)){ /* delete *slot{gv} to work around "redefine" warning */
181 SvREFCNT_dec(GvCV(gv));
184 sv_setsv_mg((SV*)gv, code_ref); /* *gv = $code_ref */
186 set_slot(methods, name, code); /* $self->{methods}{$name} = $code */
188 /* TODO: name the CODE ref if it's anonymous */
189 //code_entity = (CV*)SvRV(code_ref);
190 //if(CvANON(code_entity)
191 // && CvGV(code_entity) /* a cv under construction has no gv */ ){
193 // CvGV(code_entity) = gv;
194 // CvANON_off(code_entity);
198 MODULE = Mouse PACKAGE = Mouse::Meta::Class
201 INSTALL_SIMPLE_READER(Class, roles);
202 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id);
205 linearized_isa(SV* self)
208 SV* const stash_ref = mcall0(self, mouse_namespace); /* $self->namespace */
212 if(!(SvROK(stash_ref) && SvTYPE(SvRV(stash_ref)) == SVt_PVHV)){
213 croak("namespace() didn't return a HASH reference");
215 linearized_isa = mro_get_linear_isa((HV*)SvRV(stash_ref));
216 len = AvFILLp(linearized_isa) + 1;
218 for(i = 0; i < len; i++){
219 PUSHs(AvARRAY(linearized_isa)[i]);
224 get_all_attributes(SV* self)
227 AV* const all_attrs = mouse_get_all_attributes(aTHX_ self);
228 I32 const len = AvFILLp(all_attrs) + 1;
232 for(i = 0; i < len; i++){
233 PUSHs( MOUSE_av_at(all_attrs, i) );
237 MODULE = Mouse PACKAGE = Mouse::Meta::Role
240 INSTALL_SIMPLE_READER_WITH_KEY(Role, get_roles, roles);
241 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Role, is_anon_role, anon_serial_id);
243 MODULE = Mouse PACKAGE = Mouse::Meta::Attribute
247 INSTALL_SIMPLE_READER(Attribute, name);
248 INSTALL_SIMPLE_READER(Attribute, associated_class);
249 INSTALL_SIMPLE_READER(Attribute, accessor);
250 INSTALL_SIMPLE_READER(Attribute, reader);
251 INSTALL_SIMPLE_READER(Attribute, writer);
252 INSTALL_SIMPLE_READER(Attribute, predicate);
253 INSTALL_SIMPLE_READER(Attribute, clearer);
254 INSTALL_SIMPLE_READER(Attribute, handles);
256 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, _is_metadata, is);
257 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_required, required);
258 INSTALL_SIMPLE_READER(Attribute, default);
259 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy, lazy);
260 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy_build, lazy_build);
261 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_weak_ref, weak_ref);
262 INSTALL_SIMPLE_READER(Attribute, init_arg);
263 INSTALL_SIMPLE_READER(Attribute, type_constraint);
264 INSTALL_SIMPLE_READER(Attribute, trigger);
265 INSTALL_SIMPLE_READER(Attribute, builder);
266 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_auto_deref, auto_deref);
267 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_coerce, coerce);
268 INSTALL_SIMPLE_READER(Attribute, documentation);
271 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_accessor, accessor);
272 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_reader, reader);
273 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_writer, writer);
274 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_predicate, predicate);
275 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_clearer, clearer);
276 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_handles, handles);
278 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_default, default);
279 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_type_constraint, type_constraint);
280 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_trigger, trigger);
281 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_builder, builder);
282 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_documentation, documentation);
284 newCONSTSUB(gv_stashpvs("Mouse::Meta::Attribute", TRUE), "accessor_metaclass",
285 newSVpvs("Mouse::Meta::Method::Accessor::XS"));