From: gfx Date: Sat, 31 Oct 2009 05:45:29 +0000 (+0900) Subject: Refactor generate_isa_predicate_for-related stuff X-Git-Tag: 0.40_04~22 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMouse.git;a=commitdiff_plain;h=441964ce2aaf63287281b9084b131ecb124a3405 Refactor generate_isa_predicate_for-related stuff --- diff --git a/mouse.h b/mouse.h index 98f7f31..dc5858e 100644 --- a/mouse.h +++ b/mouse.h @@ -176,10 +176,9 @@ int mouse_tc_GlobRef (pTHX_ SV* const sv); int mouse_tc_FileHandle(pTHX_ SV* const sv); int mouse_tc_Object (pTHX_ SV* const sv); -const char* mouse_canonicalize_package_name(const char* name); +CV* generate_isa_predicate_for(pTHX_ SV* const klass, const char* const predicate_name); -XS(XS_isa_check); -XS(XS_isa_check_for_universal); +XS(XS_Mouse_parameterized_check); #endif /* !MOUSE_H */ diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index 8d0f3a8..993c1c7 100644 --- a/xs-src/Mouse.xs +++ b/xs-src/Mouse.xs @@ -120,6 +120,7 @@ PPCODE: } } + MODULE = Mouse PACKAGE = Mouse::Meta::Role BOOT: diff --git a/xs-src/MouseTypeConstraints.xs b/xs-src/MouseTypeConstraints.xs index ffae815..60fa4c4 100644 --- a/xs-src/MouseTypeConstraints.xs +++ b/xs-src/MouseTypeConstraints.xs @@ -275,7 +275,7 @@ START_MY_CXT #define MG_klass_pv(mg) ((mg)->mg_ptr) #define MG_klass_len(mg) ((mg)->mg_len) -const char* +static const char* mouse_canonicalize_package_name(const char* name){ /* "::Foo" -> "Foo" */ @@ -292,7 +292,7 @@ mouse_canonicalize_package_name(const char* name){ } static int -lookup_isa(pTHX_ HV* const instance_stash, const char* const klass_pv){ +mouse_lookup_isa(pTHX_ HV* const instance_stash, const char* const klass_pv){ AV* const linearized_isa = mro_get_linear_isa(instance_stash); SV** svp = AvARRAY(linearized_isa); SV** const end = svp + AvFILLp(linearized_isa) + 1; @@ -307,90 +307,110 @@ lookup_isa(pTHX_ HV* const instance_stash, const char* const klass_pv){ return FALSE; } -static int -instance_isa(pTHX_ SV* const instance, const MAGIC* const mg){ - dMY_CXT; - HV* const instance_stash = SvSTASH(SvRV(instance)); - GV* const instance_isa = gv_fetchmeth_autoload(instance_stash, "isa", sizeof("isa")-1, 0); - - /* the instance has no own isa method */ - if(instance_isa == NULL || GvCV(instance_isa) == GvCV(MY_CXT.universal_isa)){ - return MG_klass_stash(mg) == instance_stash - || lookup_isa(aTHX_ instance_stash, MG_klass_pv(mg)); - } - /* the instance has its own isa method */ - else { - int retval; - dSP; +int +mouse_is_an_instance_of(pTHX_ HV* const stash, SV* const instance){ + assert(stash); + assert(SvTYPE(stash) == SVt_PVHV); + + if(SvROK(instance) && SvOBJECT(SvRV(instance))){ + dMY_CXT; + HV* const instance_stash = SvSTASH(SvRV(instance)); + GV* const instance_isa = gv_fetchmeth_autoload(instance_stash, "isa", sizeof("isa")-1, 0); + + /* the instance has no own isa method */ + if(instance_isa == NULL || GvCV(instance_isa) == GvCV(MY_CXT.universal_isa)){ + return stash == instance_stash + || mouse_lookup_isa(aTHX_ instance_stash, HvNAME_get(stash)); + } + /* the instance has its own isa method */ + else { + int retval; + dSP; - ENTER; - SAVETMPS; + ENTER; + SAVETMPS; - PUSHMARK(SP); - EXTEND(SP, 2); - PUSHs(instance); - mPUSHp(MG_klass_pv(mg), MG_klass_len(mg)); - PUTBACK; + PUSHMARK(SP); + EXTEND(SP, 2); + PUSHs(instance); + mPUSHp(HvNAME_get(stash), HvNAMELEN_get(stash)); + PUTBACK; - call_sv((SV*)instance_isa, G_SCALAR); + call_sv((SV*)instance_isa, G_SCALAR); - SPAGAIN; + SPAGAIN; - retval = SvTRUEx(POPs); + retval = SvTRUEx(POPs); - PUTBACK; + PUTBACK; - FREETMPS; - LEAVE; + FREETMPS; + LEAVE; - return retval; + return retval; + } } + return FALSE; } +static int +mouse_is_an_instance_of_universal(pTHX_ SV* const data, SV* const sv){ + PERL_UNUSED_ARG(data); + return SvROK(sv) && SvOBJECT(SvRV(sv)); +} -XS(XS_isa_check){ - dVAR; - dXSARGS; - SV* sv; +static MGVTBL mouse_util_type_constraints_vtbl; /* not used, only for identity */ - assert(XSANY.any_ptr != NULL); +CV* +generate_isa_predicate_for(pTHX_ SV* const klass, const char* const predicate_name){ + STRLEN klass_len; + const char* klass_pv = SvPV_const(klass, klass_len); + CV* xsub; + SV* mg_obj; + void* mg_ptr; - if(items != 1){ - if(items < 1){ - croak("Not enough arguments for is-a predicate"); - } - else{ - croak("Too many arguments for is-a predicate"); - } + klass_pv = mouse_canonicalize_package_name(klass_pv); + + if(strNE(klass_pv, "UNIVERSAL")){ + mg_obj = (SV*)gv_stashpvn(klass_pv, klass_len, GV_ADD); + mg_ptr = (void*)mouse_is_an_instance_of; + + } + else{ + mg_obj = NULL; + mg_ptr = (void*)mouse_is_an_instance_of_universal; } - sv = ST(0); - SvGETMAGIC(sv); + xsub = newXS(predicate_name, XS_Mouse_parameterized_check, __FILE__); - ST(0) = boolSV( SvROK(sv) && SvOBJECT(SvRV(sv)) && instance_isa(aTHX_ sv, (MAGIC*)XSANY.any_ptr) ); - XSRETURN(1); -} + CvXSUBANY(xsub).any_ptr = sv_magicext( + (SV*)xsub, + mg_obj, + PERL_MAGIC_ext, + &mouse_util_type_constraints_vtbl, + mg_ptr, + 0 /* indicates static data */ + ); + if(!predicate_name){ + sv_2mortal((SV*)xsub); + } -XS(XS_isa_check_for_universal){ + return xsub; +} + +XS(XS_Mouse_parameterized_check) { dVAR; dXSARGS; - SV* sv; - PERL_UNUSED_VAR(cv); + MAGIC* const mg = (MAGIC*)XSANY.any_ptr; + typedef int (*check_fptr_t)(pTHX_ SV* const data, SV* const sv); - if(items != 1){ - if(items < 1){ - croak("Not enough arguments for is-a predicate"); - } - else{ - croak("Too many arguments for is-a predicate"); - } + if(items < 1){ + croak("Too few arguments for parameterized check functions"); } - sv = ST(0); - SvGETMAGIC(sv); - - ST(0) = boolSV( SvROK(sv) && SvOBJECT(SvRV(sv)) ); + SvGETMAGIC( ST(0) ); + ST(0) = boolSV( CALL_FPTR((check_fptr_t)mg->mg_ptr)(aTHX_ mg->mg_obj, ST(0)) ); XSRETURN(1); } diff --git a/xs-src/MouseUtil.xs b/xs-src/MouseUtil.xs index 0e2ae3b..b1b4f05 100644 --- a/xs-src/MouseUtil.xs +++ b/xs-src/MouseUtil.xs @@ -312,40 +312,28 @@ OUTPUT: RETVAL void -generate_isa_predicate_for(SV* klass, const char* predicate_name = NULL) +generate_isa_predicate_for(SV* klass, SV* predicate_name = NULL) PPCODE: { - STRLEN klass_len; - const char* klass_pv; - HV* stash; + const char* name_pv = NULL; CV* xsub; + SvGETMAGIC(klass); + if(!SvOK(klass)){ - croak("You must define a class name for generate_for"); + croak("You must define a class name"); } - klass_pv = SvPV_const(klass, klass_len); - klass_pv = mouse_canonicalize_package_name(klass_pv); - - if(strNE(klass_pv, "UNIVERSAL")){ - static MGVTBL mouse_util_type_constraints_vtbl; /* not used, only for identity */ - - xsub = newXS(predicate_name, XS_isa_check, __FILE__); - - stash = gv_stashpvn(klass_pv, klass_len, GV_ADD); - CvXSUBANY(xsub).any_ptr = sv_magicext( - (SV*)xsub, - (SV*)stash, /* mg_obj */ - PERL_MAGIC_ext, - &mouse_util_type_constraints_vtbl, - klass_pv, /* mg_ptr */ - klass_len /* mg_len */ - ); - } - else{ - xsub = newXS(predicate_name, XS_isa_check_for_universal, __FILE__); + if(predicate_name){ + SvGETMAGIC(predicate_name); + if(!SvOK(predicate_name)){ + croak("You must define a predicate_name"); + } + name_pv = SvPV_nolen_const(predicate_name); } + xsub = generate_isa_predicate_for(aTHX_ klass, name_pv); + if(predicate_name == NULL){ /* anonymous predicate */ XPUSHs( newRV_noinc((SV*)xsub) ); }