1 #define NEED_newSVpvn_flags_GLOBAL
8 SV* mouse_get_attribute;
9 SV* mouse_get_attribute_list;
12 #define MOUSE_xc_gen(a) MOUSE_av_at((a), MOUSE_XC_GEN)
13 #define MOUSE_xc_attrall(a) ( (AV*)MOUSE_av_at((a), MOUSE_XC_ATTRALL) )
14 #define MOUSE_xc_buildall(a) ( (AV*)MOUSE_av_at((a), MOUSE_XC_BUILDALL) )
15 #define MOUSE_xc_demolishall(a) ( (AV*)MOUSE_av_at((a), MOUSE_XC_DEOLISHALL) )
17 /* Mouse XS Metaclass object */
19 MOUSE_XC_GEN, /* class generation */
20 MOUSE_XC_ATTRALL, /* all the attributes */
21 MOUSE_XC_BUILDALL, /* all the BUILD methods */
22 MOUSE_XC_DEMOLISHALL, /* all the DEMOLISH methods */
27 static MGVTBL mouse_xc_vtbl; /* for identity */
30 mouse_class_push_attribute_list(pTHX_ SV* const metaclass, AV* const attrall, HV* const seen){
34 /* $meta->get_attribute_list */
39 n = call_sv(mouse_get_attribute_list, G_ARRAY | G_METHOD);
40 for(NOOP; n > 0; n--){
47 if(hv_exists_ent(seen, name, 0U)){
50 (void)hv_store_ent(seen, name, &PL_sv_undef, 0U);
52 av_push(attrall, newSVsv( mcall1(metaclass, mouse_get_attribute, name) ));
57 mouse_class_update_xc(pTHX_ SV* const metaclass PERL_UNUSED_DECL, HV* const stash, AV* const xc) {
58 AV* const linearized_isa = mro_get_linear_isa(stash);
59 I32 const len = AvFILLp(linearized_isa);
61 AV* const attrall = newAV();
62 AV* const buildall = newAV();
63 AV* const demolishall = newAV();
64 HV* const seen = newHV(); /* for attributes */
69 sv_2mortal((SV*)seen);
71 /* old data will be delete at the end of the perl scope */
72 av_delete(xc, MOUSE_XC_DEMOLISHALL, 0x00);
73 av_delete(xc, MOUSE_XC_BUILDALL, 0x00);
74 av_delete(xc, MOUSE_XC_ATTRALL, 0x00);
76 SvREFCNT_inc_simple_void_NN(linearized_isa);
77 sv_2mortal((SV*)linearized_isa);
81 av_store(xc, MOUSE_XC_ATTRALL, (SV*)attrall);
82 av_store(xc, MOUSE_XC_BUILDALL, (SV*)buildall);
83 av_store(xc, MOUSE_XC_DEMOLISHALL, (SV*)demolishall);
85 for(i = 0; i < len; i++){
86 SV* const klass = MOUSE_av_at(linearized_isa, i);
90 gv = stash_fetchs(stash, "BUILD", FALSE);
92 av_push(buildall, newRV_inc((SV*)GvCV(gv)));
95 gv = stash_fetchs(stash, "DEMOLISH", FALSE);
97 av_push(demolishall, newRV_inc((SV*)GvCV(gv)));
101 meta = get_metaclass_by_name(klass);
103 continue; /* skip non-Mouse classes */
106 mouse_class_push_attribute_list(aTHX_ meta, attrall, seen);
112 sv_setuv(MOUSE_xc_gen(xc), mro_get_pkg_gen(stash));
116 mouse_get_xc(pTHX_ SV* const metaclass) {
122 if(!IsObject(metaclass)){
123 croak("Not a Mouse metaclass");
126 mg = mouse_mg_find(aTHX_ SvRV(metaclass), &mouse_xc_vtbl, 0x00);
128 SV* const package = get_slot(metaclass, mouse_package);
130 stash = gv_stashsv(package, TRUE);
133 mg = sv_magicext(SvRV(metaclass), (SV*)xc, PERL_MAGIC_ext, &mouse_xc_vtbl, (char*)stash, HEf_SVKEY);
134 SvREFCNT_dec(xc); /* refcnt++ in sv_magicext */
136 av_extend(xc, MOUSE_XC_last - 1);
137 av_store(xc, MOUSE_XC_GEN, newSViv(0));
140 stash = (HV*)MOUSE_mg_ptr(mg);
141 xc = (AV*)MOUSE_mg_obj(mg);
144 assert(SvTYPE(stash) == SVt_PVAV);
147 assert(SvTYPE(xc) == SVt_PVAV);
150 gen = MOUSE_xc_gen(xc);
151 if(SvUV(gen) != mro_get_pkg_gen(stash)){
152 mouse_class_update_xc(aTHX_ metaclass, stash, xc);
159 mouse_get_all_attributes(pTHX_ SV* const metaclass) {
160 AV* const xc = mouse_get_xc(aTHX_ metaclass);
161 return MOUSE_xc_attrall(xc);
164 MODULE = Mouse PACKAGE = Mouse
169 mouse_package = newSVpvs_share("package");
170 mouse_namespace = newSVpvs_share("namespace");
171 mouse_methods = newSVpvs_share("methods");
172 mouse_name = newSVpvs_share("name");
174 mouse_get_attribute = newSVpvs_share("get_attribute");
175 mouse_get_attribute_list = newSVpvs_share("get_attribute_list");
177 MOUSE_CALL_BOOT(Mouse__Util);
178 MOUSE_CALL_BOOT(Mouse__Util__TypeConstraints);
179 MOUSE_CALL_BOOT(Mouse__Meta__Method__Accessor__XS);
182 MODULE = Mouse PACKAGE = Mouse::Meta::Module
185 INSTALL_SIMPLE_READER_WITH_KEY(Module, name, package);
186 INSTALL_SIMPLE_READER_WITH_KEY(Module, _method_map, methods);
187 INSTALL_SIMPLE_READER_WITH_KEY(Module, _attribute_map, attributes);
193 SV* const package = get_slot(self, mouse_package);
194 if(!(package && SvOK(package))){
195 croak("No package name defined");
197 RETVAL = gv_stashsv(package, GV_ADDMULTI);
202 # ignore extra arguments for extensibility
204 add_method(SV* self, SV* name, SV* code, ...)
207 SV* const package = get_slot(self, mouse_package); /* $self->{package} */
208 SV* const methods = get_slot(self, mouse_methods); /* $self->{methods} */
212 if(!(package && SvOK(package))){
213 croak("No package name defined");
220 mouse_throw_error(self, NULL, "You must define a method name");
223 mouse_throw_error(self, NULL, "You must define a CODE reference");
227 if(SvTYPE(SvRV(code_ref)) != SVt_PVCV){
228 SV* sv = code_ref; /* used in tryAMAGICunDEREF */
229 SV** sp = &sv; /* used in tryAMAGICunDEREF */
230 tryAMAGICunDEREF(to_cv); /* try \&{$code} */
231 if(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV){
232 mouse_throw_error(self, NULL, "Not a CODE reference");
237 /* *{$package . '::' . $name} -> *gv */
238 gv = gv_fetchpv(form("%"SVf"::%"SVf, package, name), GV_ADDMULTI, SVt_PVCV);
239 if(GvCVu(gv)){ /* delete *slot{gv} to work around "redefine" warning */
240 SvREFCNT_dec(GvCV(gv));
243 sv_setsv_mg((SV*)gv, code_ref); /* *gv = $code_ref */
245 set_slot(methods, name, code); /* $self->{methods}{$name} = $code */
247 /* TODO: name the CODE ref if it's anonymous */
248 //code_entity = (CV*)SvRV(code_ref);
249 //if(CvANON(code_entity)
250 // && CvGV(code_entity) /* a cv under construction has no gv */ ){
252 // CvGV(code_entity) = gv;
253 // CvANON_off(code_entity);
257 MODULE = Mouse PACKAGE = Mouse::Meta::Class
260 INSTALL_SIMPLE_READER(Class, roles);
261 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id);
264 linearized_isa(SV* self)
267 SV* const stash_ref = mcall0(self, mouse_namespace); /* $self->namespace */
271 if(!(SvROK(stash_ref) && SvTYPE(SvRV(stash_ref)) == SVt_PVHV)){
272 croak("namespace() didn't return a HASH reference");
274 linearized_isa = mro_get_linear_isa((HV*)SvRV(stash_ref));
275 len = AvFILLp(linearized_isa) + 1;
277 for(i = 0; i < len; i++){
278 PUSHs(AvARRAY(linearized_isa)[i]);
283 get_all_attributes(SV* self)
286 AV* const all_attrs = mouse_get_all_attributes(aTHX_ self);
287 I32 const len = AvFILLp(all_attrs) + 1;
291 for(i = 0; i < len; i++){
292 PUSHs( MOUSE_av_at(all_attrs, i) );
296 MODULE = Mouse PACKAGE = Mouse::Meta::Role
299 INSTALL_SIMPLE_READER_WITH_KEY(Role, get_roles, roles);
300 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Role, is_anon_role, anon_serial_id);
302 MODULE = Mouse PACKAGE = Mouse::Meta::Attribute
306 INSTALL_SIMPLE_READER(Attribute, name);
307 INSTALL_SIMPLE_READER(Attribute, associated_class);
308 INSTALL_SIMPLE_READER(Attribute, accessor);
309 INSTALL_SIMPLE_READER(Attribute, reader);
310 INSTALL_SIMPLE_READER(Attribute, writer);
311 INSTALL_SIMPLE_READER(Attribute, predicate);
312 INSTALL_SIMPLE_READER(Attribute, clearer);
313 INSTALL_SIMPLE_READER(Attribute, handles);
315 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, _is_metadata, is);
316 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_required, required);
317 INSTALL_SIMPLE_READER(Attribute, default);
318 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy, lazy);
319 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_lazy_build, lazy_build);
320 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, is_weak_ref, weak_ref);
321 INSTALL_SIMPLE_READER(Attribute, init_arg);
322 INSTALL_SIMPLE_READER(Attribute, type_constraint);
323 INSTALL_SIMPLE_READER(Attribute, trigger);
324 INSTALL_SIMPLE_READER(Attribute, builder);
325 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_auto_deref, auto_deref);
326 INSTALL_SIMPLE_READER_WITH_KEY(Attribute, should_coerce, coerce);
327 INSTALL_SIMPLE_READER(Attribute, documentation);
330 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_accessor, accessor);
331 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_reader, reader);
332 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_writer, writer);
333 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_predicate, predicate);
334 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_clearer, clearer);
335 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_handles, handles);
337 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_default, default);
338 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_type_constraint, type_constraint);
339 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_trigger, trigger);
340 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_builder, builder);
341 INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_documentation, documentation);
343 newCONSTSUB(gv_stashpvs("Mouse::Meta::Attribute", TRUE), "accessor_metaclass",
344 newSVpvs("Mouse::Meta::Method::Accessor::XS"));