From: Fuji, Goro Date: Thu, 23 Sep 2010 05:53:32 +0000 (+0900) Subject: Generalize inheritable class accessors X-Git-Tag: 0.71~31 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=fad99075beae804374b22c9e356f90daf23bbc05;p=gitmo%2FMouse.git Generalize inheritable class accessors --- diff --git a/mouse.h b/mouse.h index 88d17da..0ce6916 100644 --- a/mouse.h +++ b/mouse.h @@ -116,26 +116,37 @@ void mouse_instance_weaken_slot(pTHX_ SV* const instance, SV* const slot); #define get_slots(self, key) get_slot(self, sv_2mortal(newSVpvs_share(key))) #define set_slots(self, key, value) set_slot(self, sv_2mortal(newSVpvs_share(key)), value) -/* mouse_simle_accessor.xs */ +/* mouse_simle_accessor.xs for meta object protocols */ #define INSTALL_SIMPLE_READER(klass, name) \ INSTALL_SIMPLE_READER_WITH_KEY(klass, name, name) #define INSTALL_SIMPLE_READER_WITH_KEY(klass, name, key) \ - (void)mouse_simple_accessor_generate(aTHX_ "Mouse::Meta::" #klass "::" #name, #key, sizeof(#key)-1, XS_Mouse_simple_reader, NULL, 0) + (void)mouse_simple_accessor_generate(aTHX_ "Mouse::Meta::" #klass "::" \ + #name, #key, sizeof(#key)-1, XS_Mouse_simple_reader, NULL, 0) #define INSTALL_CLASS_HOLDER_SV(klass, name, dsv) \ - (void)mouse_simple_accessor_generate(aTHX_ "Mouse::Meta::" #klass "::" #name, #name, sizeof(#name)-1, XS_Mouse_simple_reader, (dsv), HEf_SVKEY) + (void)mouse_simple_accessor_generate(aTHX_ "Mouse::Meta::" #klass "::" \ + #name, #name, sizeof(#name)-1, XS_Mouse_simple_reader, (dsv), HEf_SVKEY) #define INSTALL_CLASS_HOLDER(klass, name, ds) \ INSTALL_CLASS_HOLDER_SV(klass, name, newSVpvs(ds)) #define INSTALL_SIMPLE_WRITER(klass, name) \ NSTALL_SIMPLE_WRITER_WITH_KEY(klass, name, name) #define INSTALL_SIMPLE_WRITER_WITH_KEY(klass, name, key) \ - (void)mouse_simple_accessor_generate(aTHX_ "Mouse::Meta::" #klass "::" #name, #key, sizeof(#key)-1, XS_Mouse_simple_writer, NULL, 0) + (void)mouse_simple_accessor_generate(aTHX_ "Mouse::Meta::" #klass "::" \ + #name, #key, sizeof(#key)-1, XS_Mouse_simple_writer, NULL, 0) #define INSTALL_SIMPLE_PREDICATE(klass, name) \ INSTALL_SIMPLE_PREDICATE_WITH_KEY(klass, name, name) #define INSTALL_SIMPLE_PREDICATE_WITH_KEY(klass, name, key) \ - (void)mouse_simple_accessor_generate(aTHX_ "Mouse::Meta::" #klass "::" #name, #key, sizeof(#key)-1, XS_Mouse_simple_predicate, NULL, 0) + (void)mouse_simple_accessor_generate(aTHX_ "Mouse::Meta::" #klass "::" \ + #name, #key, sizeof(#key)-1, XS_Mouse_simple_predicate, NULL, 0) + +/* generate inhertiable class accessors for Mouse::Meta::Class */ +#define INSTALL_INHERITABLE_CLASS_ACCESSOR(name) \ + INSTALL_INHERITABLE_CLASS_ACCESSOR_WITH_KEY(name, name) +#define INSTALL_INHERITABLE_CLASS_ACCESSOR_WITH_KEY(name, key) \ + (void)mouse_simple_accessor_generate(aTHX_ "Mouse::Meta::Class::" #name,\ + #key, sizeof(#key)-1, XS_Mouse_inheritable_class_accessor, NULL, 0) CV* mouse_simple_accessor_generate(pTHX_ const char* const fq_name, const char* const key, I32 const keylen, XSUBADDR_t const accessor_impl, void* const dptr, I32 const dlen); @@ -150,6 +161,8 @@ XS(XS_Mouse_accessor); XS(XS_Mouse_reader); XS(XS_Mouse_writer); +XS(XS_Mouse_inheritable_class_accessor); + /* type constraints */ int mouse_tc_check(pTHX_ SV* const tc, SV* const sv); diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index efd1e94..431d7c5 100644 --- a/xs-src/Mouse.xs +++ b/xs-src/Mouse.xs @@ -530,6 +530,8 @@ BOOT: INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id); INSTALL_SIMPLE_READER(Class, is_immutable); + INSTALL_INHERITABLE_CLASS_ACCESSOR(strict_constructor); + INSTALL_CLASS_HOLDER(Class, method_metaclass, "Mouse::Meta::Method"); INSTALL_CLASS_HOLDER(Class, attribute_metaclass, "Mouse::Meta::Attribute"); INSTALL_CLASS_HOLDER(Class, constructor_class, "Mouse::Meta::Method::Constructor::XS"); @@ -616,45 +618,6 @@ CODE: mouse_class_initialize_object(aTHX_ meta, object, args, is_cloning); } -void -strict_constructor(SV* self, SV* value = NULL) -CODE: -{ - SV* const slot = sv_2mortal(newSVpvs_share("strict_constructor")); - SV* const stash_ref = mcall0(self, mouse_namespace); - HV* stash; - - if(!(SvROK(stash_ref) && SvTYPE(SvRV(stash_ref)) == SVt_PVHV)) { - croak("namespace() didn't return a HASH reference"); - } - stash = (HV*)SvRV(stash_ref); - - if(value) { /* setter */ - set_slot(self, slot, value); - mro_method_changed_in(stash); - } - - value = get_slot(self, slot); - - if(!value) { - AV* const isa = mro_get_linear_isa(stash); - I32 const len = av_len(isa) + 1; - I32 i; - for(i = 1; i < len; i++) { - SV* const klass = MOUSE_av_at(isa, i); - SV* const meta = get_metaclass(klass); - if(!SvOK(meta)){ - continue; /* skip non-Mouse classes */ - } - value = get_slot(meta, slot); - if(value) { - break; - } - } - } - ST(0) = value ? value : &PL_sv_no; -} - MODULE = Mouse PACKAGE = Mouse::Meta::Role BOOT: diff --git a/xs-src/MouseAccessor.xs b/xs-src/MouseAccessor.xs index d3d046a..0d0d448 100644 --- a/xs-src/MouseAccessor.xs +++ b/xs-src/MouseAccessor.xs @@ -183,7 +183,8 @@ XS(XS_Mouse_accessor) } else{ mouse_throw_error(MOUSE_mg_attribute(mg), NULL, - "Expected exactly one or two argument for an accessor"); + "Expected exactly one or two argument for an accessor of %"SVf, + MOUSE_mg_slot(mg)); } } @@ -196,7 +197,8 @@ XS(XS_Mouse_reader) if (items != 1) { mouse_throw_error(MOUSE_mg_attribute(mg), NULL, - "Cannot assign a value to a read-only accessor"); + "Cannot assign a value to a read-only accessor of %"SVf, + MOUSE_mg_slot(mg)); } SP -= items; /* PPCODE */ @@ -213,7 +215,8 @@ XS(XS_Mouse_writer) if (items != 2) { mouse_throw_error(MOUSE_mg_attribute(mg), NULL, - "Too few arguments for a write-only accessor"); + "Too few arguments for a write-only accessor of %"SVf, + MOUSE_mg_slot(mg)); } SP -= items; /* PPCODE */ @@ -232,7 +235,9 @@ mouse_accessor_get_mg(pTHX_ CV* const xsub){ */ CV* -mouse_simple_accessor_generate(pTHX_ const char* const fq_name, const char* const key, I32 const keylen, XSUBADDR_t const accessor_impl, void* const dptr, I32 const dlen){ +mouse_simple_accessor_generate(pTHX_ + const char* const fq_name, const char* const key, I32 const keylen, + XSUBADDR_t const accessor_impl, void* const dptr, I32 const dlen) { CV* const xsub = newXS((char*)fq_name, accessor_impl, __FILE__); SV* const slot = newSVpvn_share(key, keylen, 0U); MAGIC* mg; @@ -264,7 +269,8 @@ XS(XS_Mouse_simple_reader) SV* value; if (items != 1) { - croak("Expected exactly one argument for a reader for '%"SVf"'", MOUSE_mg_slot(mg)); + croak("Expected exactly one argument for a reader of %"SVf, + MOUSE_mg_slot(mg)); } value = get_slot(self, MOUSE_mg_slot(mg)); @@ -291,7 +297,8 @@ XS(XS_Mouse_simple_writer) SV* const slot = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr); if (items != 2) { - croak("Expected exactly two argument for a writer for '%"SVf"'", slot); + croak("Expected exactly two argument for a writer of %"SVf, + slot); } ST(0) = set_slot(self, slot, ST(1)); @@ -306,7 +313,8 @@ XS(XS_Mouse_simple_clearer) SV* value; if (items != 1) { - croak("Expected exactly one argument for a clearer for '%"SVf"'", slot); + croak("Expected exactly one argument for a clearer of %"SVf, + slot); } value = delete_slot(self, slot); @@ -321,13 +329,71 @@ XS(XS_Mouse_simple_predicate) SV* const slot = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr); if (items != 1) { - croak("Expected exactly one argument for a predicate for '%"SVf"'", slot); + croak("Expected exactly one argument for a predicate of %"SVf, slot); } ST(0) = boolSV( has_slot(self, slot) ); XSRETURN(1); } +/* Class::Data::Inheritable-like class accessor */ +XS(XS_Mouse_inheritable_class_accessor) { + dVAR; dXSARGS; + dMOUSE_self; + SV* const slot = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr); + SV* value; + SV* stash_ref; + HV* stash; + + if(items == 1){ /* reader */ + value = NULL; + } + else if (items == 2){ /* writer */ + value = ST(1); + } + else{ + croak("Expected exactly one or two argument for a class data accessor" + "of %"SVf, slot); + value = NULL; /* -Wuninitialized */ + } + + stash_ref= mcall0(self, mouse_namespace); + if(!(SvROK(stash_ref) && SvTYPE(SvRV(stash_ref)) == SVt_PVHV)) { + croak("namespace() didn't return a HASH reference"); + } + stash = (HV*)SvRV(stash_ref); + + if(!value) { /* reader */ + value = get_slot(self, slot); + if(!value) { + AV* const isa = mro_get_linear_isa(stash); + I32 const len = av_len(isa) + 1; + I32 i; + for(i = 1; i < len; i++) { + SV* const klass = MOUSE_av_at(isa, i); + SV* const meta = get_metaclass(klass); + if(!SvOK(meta)){ + continue; /* skip non-Mouse classes */ + } + value = get_slot(meta, slot); + if(value) { + break; + } + } + if(!value) { + value = &PL_sv_undef; + } + } + } + else { /* writer */ + set_slot(self, slot, value); + mro_method_changed_in(stash); + } + + ST(0) = value; + XSRETURN(1); +} + /* simple instance slot accessor (or Mouse::Meta::Instance) */ SV*