typedef int (*check_fptr_t)(pTHX_ SV* const data, SV* const sv);
+/*
+ NOTE: mouse_tc_check() handles GETMAGIC
+*/
int
mouse_tc_check(pTHX_ SV* const tc_code, SV* const sv) {
CV* const cv = (CV*)SvRV(tc_code);
assert(SvTYPE(cv) == SVt_PVCV);
+ SvGETMAGIC(sv);
if(CvXSUB(cv) == XS_Mouse_constraint_check){ /* built-in type constraints */
MAGIC* const mg = (MAGIC*)CvXSUBANY(cv).any_ptr;
call_sv(tc_code, G_SCALAR);
SPAGAIN;
- ok = SvTRUEx(POPs);
+ ok = sv_true(POPs);
PUTBACK;
FREETMPS;
mouse_tc_Bool(pTHX_ SV* const data PERL_UNUSED_DECL, SV* const sv) {
assert(sv);
- if(SvTRUE(sv)){
+ if(sv_true(sv)){
if(SvIOKp(sv)){
return SvIVX(sv) == 1;
}
}
int
-mouse_tc_ScalarRef(pTHX_ SV* const data PERL_UNUSED_DECL, SV* const sv) {
+mouse_tc_ScalarRef(pTHX_ SV* const data PERL_UNUSED_DECL, SV* sv) {
assert(sv);
- return SvROK(sv) && !SvOBJECT(SvRV(sv)) && (SvTYPE(SvRV(sv)) <= SVt_PVLV && !isGV(SvRV(sv)));
+ if(SvROK(sv)){
+ sv = SvRV(sv);
+ return !SvOBJECT(sv) && (SvTYPE(sv) <= SVt_PVLV && !isGV(sv));
+ }
+ return FALSE;
}
int
I32 i;
for(i = 0; i < len; i++){
SV* const value = *av_fetch(av, i, TRUE);
- SvGETMAGIC(value);
if(!mouse_tc_check(aTHX_ param, value)){
return FALSE;
}
hv_iterinit(hv);
while((he = hv_iternext(hv))){
SV* const value = hv_iterval(hv, he);
- SvGETMAGIC(value);
if(!mouse_tc_check(aTHX_ param, value)){
hv_iterinit(hv); /* reset */
return FALSE;
return FALSE;
}
+#define find_method_pvn(a, b, c) mouse_stash_find_method(aTHX_ a, b, c)
+#define find_method_pvs(a, b) mouse_stash_find_method(aTHX_ a, STR_WITH_LEN(b))
+
+static inline GV*
+mouse_stash_find_method(pTHX_ HV* const stash, const char* const name, I32 const namelen){
+ GV** const gvp = (GV**)hv_fetch(stash, name, namelen, FALSE);
+ if(gvp && isGV(*gvp) && GvCV(*gvp)){ /* shortcut */
+ return *gvp;
+ }
+
+ return gv_fetchmeth_autoload(stash, name, namelen, 0);
+}
+
int
mouse_is_an_instance_of(pTHX_ HV* const stash, SV* const instance){
assert(stash);
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);
+ GV* const instance_isa = find_method_pvs(instance_stash, "isa");
/* the instance has no own isa method */
if(instance_isa == NULL || GvCV(instance_isa) == GvCV(MY_CXT.universal_isa)){
call_sv((SV*)instance_isa, G_SCALAR);
SPAGAIN;
-
- retval = SvTRUEx(POPs);
-
+ retval = sv_true(POPs);
PUTBACK;
FREETMPS;
if(IsObject(instance)){
dMY_CXT;
HV* const mystash = SvSTASH(SvRV(instance));
- GV* const mycan = gv_fetchmeth_autoload(mystash, "can", sizeof("can")-1, 0);
- bool const use_builtin = (mycan == NULL || GvCV(mycan) == GvCV(MY_CXT.universal_isa)) ? TRUE : FALSE;
+ GV* const mycan = find_method_pvs(mystash, "can");
+ bool const use_builtin = (mycan == NULL || GvCV(mycan) == GvCV(MY_CXT.universal_can)) ? TRUE : FALSE;
I32 const len = AvFILLp(methods) + 1;
I32 i;
for(i = 0; i < len; i++){
SV* const name = MOUSE_av_at(methods, i);
if(use_builtin){
- if(!gv_fetchmeth_autoload(mystash, SvPVX(name), SvCUR(name), 0)){
+ if(!find_method_pvn(mystash, SvPVX(name), SvCUR(name))){
return FALSE;
}
}
call_method("can", G_SCALAR);
SPAGAIN;
- ok = SvTRUE(TOPs);
- (void)POPs;
+ ok = sv_true(POPs);
PUTBACK;
FREETMPS;
param, /* mg_obj: refcnt will be increased */
PERL_MAGIC_ext,
&mouse_util_type_constraints_vtbl,
- (void*)fptr, /* mg_ptr */
+ (char*)fptr, /* mg_ptr */
0 /* mg_len: 0 for static data */
);
STRLEN klass_len;
const char* klass_pv = SvPV_const(klass, klass_len);
SV* param;
- void* fptr;
+ check_fptr_t fptr;
klass_pv = mouse_canonicalize_package_name(klass_pv);
if(strNE(klass_pv, "UNIVERSAL")){
param = (SV*)gv_stashpvn(klass_pv, klass_len, GV_ADD);
- fptr = (void*)mouse_is_an_instance_of;
+ fptr = (check_fptr_t)mouse_is_an_instance_of;
}
else{
param = NULL;
- fptr = (void*)mouse_is_an_instance_of_universal;
+ fptr = (check_fptr_t)mouse_is_an_instance_of_universal;
}
return mouse_tc_generate(aTHX_ predicate_name, fptr, param);
else{
check = newRV_inc((SV*)mouse_tc_generate(aTHX_ NULL, (check_fptr_t)mouse_types_check, (SV*)checks));
}
- set_slots(self, "compiled_type_constraint", check);
+ (void)set_slots(self, "compiled_type_constraint", check);
}