X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs-src%2FMouseTypeConstraints.xs;h=41f70d70da05d449d148bae921590a1a14ff458d;hb=28ba5a267651519bd096e2e6ac43add4807a9b86;hp=60fa4c463473ab53dd487a8c4caa264ec7e2e8a1;hpb=441964ce2aaf63287281b9084b131ecb124a3405;p=gitmo%2FMouse.git diff --git a/xs-src/MouseTypeConstraints.xs b/xs-src/MouseTypeConstraints.xs index 60fa4c4..41f70d7 100644 --- a/xs-src/MouseTypeConstraints.xs +++ b/xs-src/MouseTypeConstraints.xs @@ -14,12 +14,31 @@ #define SvRXOK(sv) (SvROK(sv) && SvMAGICAL(SvRV(sv)) && mg_find(SvRV(sv), PERL_MAGIC_qr)) #endif +typedef int (*check_fptr_t)(pTHX_ SV* const data, SV* const sv); + int mouse_tc_check(pTHX_ SV* const tc_code, SV* const sv) { - if(SvIOK(tc_code)){ /* built-in type constraints */ - return mouse_builtin_tc_check(aTHX_ SvIVX(tc_code), sv); + CV* const cv = (CV*)SvRV(tc_code); + assert(SvTYPE(cv) == Svt_PVCV); + + if(CvISXSUB(cv)){ /* can be built-in tc */ + if(CvXSUB(cv) == XS_Mouse__Util__TypeConstraints_Item){ + assert(CvXSUBANY(cv).any_iv > 0); + + return mouse_builtin_tc_check(aTHX_ CvXSUBANY(cv).any_iv, sv); + } + else if(CvXSUB(cv) == XS_Mouse_parameterized_check){ + MAGIC* const mg = (MAGIC*)CvXSUBANY(cv).any_ptr; + + assert(CvXSUBANY(cv).any_ptr != NULL); + + /* call the check function directly, skipping call_sv() */ + return CALL_FPTR((check_fptr_t)mg->mg_ptr)(aTHX_ mg->mg_obj, sv); + } } - else { + + /* user-defined type constraints */ + { int ok; dSP; @@ -67,11 +86,10 @@ mouse_builtin_tc_check(pTHX_ mouse_tc const tc, SV* const sv) { case MOUSE_TC_CLASS_NAME: return mouse_tc_ClassName(aTHX_ sv); case MOUSE_TC_ROLE_NAME: return mouse_tc_RoleName(aTHX_ sv); default: - /* custom type constraints */ NOOP; } - croak("Custom type constraint is not yet implemented"); + croak("Mouse-panic: unrecognized type constraint id: %d", (int)tc); return FALSE; /* not reached */ } @@ -90,22 +108,23 @@ mouse_tc_Any(pTHX_ SV* const sv PERL_UNUSED_DECL) { int mouse_tc_Bool(pTHX_ SV* const sv) { assert(sv); - if(SvOK(sv)){ + + if(SvTRUE(sv)){ if(SvIOKp(sv)){ - return SvIVX(sv) == 1 || SvIVX(sv) == 0; + return SvIVX(sv) == 1; } else if(SvNOKp(sv)){ - return SvNVX(sv) == 1.0 || SvNVX(sv) == 0.0; + return SvNVX(sv) == 1.0; } - else if(SvPOKp(sv)){ /* "" or "1" or "0" */ - return SvCUR(sv) == 0 - || ( SvCUR(sv) == 1 && ( SvPVX(sv)[0] == '1' || SvPVX(sv)[0] == '0' ) ); + else if(SvPOKp(sv)){ /* "1" */ + return SvCUR(sv) == 1 && SvPVX(sv)[0] == '1'; } else{ return FALSE; } } else{ + /* false must be boolean */ return TRUE; } } @@ -184,7 +203,7 @@ mouse_tc_RoleName(pTHX_ SV* const sv) { meta = POPs; PUTBACK; - ok = is_instance_of(meta, newSVpvs_flags("Mouse::Meta::Role", SVs_TEMP)); + ok = is_an_instance_of("Mouse::Meta::Role", meta); FREETMPS; LEAVE; @@ -252,7 +271,7 @@ mouse_tc_FileHandle(pTHX_ SV* const sv) { } } - return is_instance_of(sv, newSVpvs_flags("IO::Handle", SVs_TEMP)); + return is_an_instance_of("IO::Handle", sv); } int @@ -312,7 +331,7 @@ 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))){ + if(IsObject(instance)){ dMY_CXT; HV* const instance_stash = SvSTASH(SvRV(instance)); GV* const instance_isa = gv_fetchmeth_autoload(instance_stash, "isa", sizeof("isa")-1, 0); @@ -362,7 +381,7 @@ mouse_is_an_instance_of_universal(pTHX_ SV* const data, SV* const sv){ static MGVTBL mouse_util_type_constraints_vtbl; /* not used, only for identity */ CV* -generate_isa_predicate_for(pTHX_ SV* const klass, const char* const predicate_name){ +mouse_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; @@ -403,7 +422,6 @@ XS(XS_Mouse_parameterized_check) { dVAR; dXSARGS; MAGIC* const mg = (MAGIC*)XSANY.any_ptr; - typedef int (*check_fptr_t)(pTHX_ SV* const data, SV* const sv); if(items < 1){ croak("Too few arguments for parameterized check functions");