X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMouse.git;a=blobdiff_plain;f=xs-src%2FMouseAccessor.xs;h=dd89a007157314e2dc5a0d5a57dca0aaf36a3db4;hp=a9de90397a873dfb4525fdef4ec92ffc4ccbc51e;hb=6fe2272b04003d989c299dae495c4c6f9730dabc;hpb=646c0371bdfda5817f842c54577c4d5605a4c3c0 diff --git a/xs-src/MouseAccessor.xs b/xs-src/MouseAccessor.xs index a9de903..dd89a00 100644 --- a/xs-src/MouseAccessor.xs +++ b/xs-src/MouseAccessor.xs @@ -2,7 +2,7 @@ #define CHECK_INSTANCE(instance) STMT_START{ \ if(!(SvROK(instance) && SvTYPE(SvRV(instance)) == SVt_PVHV)){ \ - croak("Invalid object for instance managers"); \ + croak("Invalid object instance"); \ } \ } STMT_END @@ -52,8 +52,6 @@ static MGVTBL mouse_accessor_vtbl; /* MAGIC identity */ SV* mouse_accessor_get_self(pTHX_ I32 const ax, I32 const items, CV* const cv) { - SV* self; - if(items < 1){ croak("Too few arguments for %s", GvNAME(CvGV(cv))); } @@ -62,11 +60,7 @@ mouse_accessor_get_self(pTHX_ I32 const ax, I32 const items, CV* const cv) { * before calling methods, so SvGETMAGIC(self) is not necessarily needed here. */ - self = ST(0); - if(!IsObject(self)){ - croak("Cant call %s as a class method", GvNAME(CvGV(cv))); - } - return self; + return ST(0); } @@ -168,18 +162,11 @@ mouse_apply_type_constraint(pTHX_ AV* const xa, SV* value, U16 const flags){ } if(!SvOK(MOUSE_xa_tc_code(xa))){ - XS(XS_Mouse__Util__TypeConstraints_Item); /* prototype defined in Mouse.xs */ - tc_code = mcall0s(tc, "_compiled_type_constraint"); + av_store(xa, MOUSE_XA_TC_CODE, newSVsv(tc_code)); - if(SvROK(tc_code) && SvTYPE(SvRV(tc_code)) - && CvXSUB((CV*)SvRV(tc_code)) == XS_Mouse__Util__TypeConstraints_Item){ - /* built-in type constraints */ - mouse_tc const id = CvXSUBANY((CV*)SvRV(tc_code)).any_i32; - av_store(xa, MOUSE_XA_TC_CODE, newSViv(id)); - } - else{ - av_store(xa, MOUSE_XA_TC_CODE, newSVsv(tc_code)); + if(!(SvROK(tc_code) && SvTYPE(SvRV(tc_code)) == SVt_PVCV)){ + mouse_throw_error(MOUSE_xa_attribute(xa), tc, "Not a CODE reference"); } } else{ @@ -196,51 +183,58 @@ mouse_apply_type_constraint(pTHX_ AV* const xa, SV* value, U16 const flags){ return value; } +#define PUSH_VALUE(value, flags) STMT_START { \ + if((flags) & MOUSEf_ATTR_SHOULD_AUTO_DEREF && GIMME_V == G_ARRAY){ \ + mouse_push_values(aTHX_ value, (flags)); \ + } \ + else{ \ + dSP; \ + XPUSHs(value ? value : &PL_sv_undef); \ + PUTBACK; \ + } \ + } STMT_END \ /* pushes return values, does auto-deref if needed */ static void mouse_push_values(pTHX_ SV* const value, U16 const flags){ dSP; - if(flags & MOUSEf_ATTR_SHOULD_AUTO_DEREF && GIMME_V == G_ARRAY){ - if(!(value && SvOK(value))){ - return; - } + assert( flags & MOUSEf_ATTR_SHOULD_AUTO_DEREF && GIMME_V == G_ARRAY ); - if(flags & MOUSEf_TC_IS_ARRAYREF){ - AV* const av = (AV*)SvRV(value); - I32 len; - I32 i; + if(!(value && SvOK(value))){ + return; + } - if(SvTYPE(av) != SVt_PVAV){ - croak("Mouse-panic: Not an ARRAY reference"); - } + if(flags & MOUSEf_TC_IS_ARRAYREF){ + AV* const av = (AV*)SvRV(value); + I32 len; + I32 i; - len = av_len(av) + 1; - EXTEND(SP, len); - for(i = 0; i < len; i++){ - SV** const svp = av_fetch(av, i, FALSE); - PUSHs(svp ? *svp : &PL_sv_undef); - } + if(SvTYPE(av) != SVt_PVAV){ + croak("Mouse-panic: Not an ARRAY reference"); } - else if(flags & MOUSEf_TC_IS_HASHREF){ - HV* const hv = (HV*)SvRV(value); - HE* he; - if(SvTYPE(hv) != SVt_PVHV){ - croak("Mouse-panic: Not a HASH reference"); - } - - hv_iterinit(hv); - while((he = hv_iternext(hv))){ - EXTEND(SP, 2); - PUSHs(hv_iterkeysv(he)); - PUSHs(hv_iterval(hv, he)); - } + len = av_len(av) + 1; + EXTEND(SP, len); + for(i = 0; i < len; i++){ + SV** const svp = av_fetch(av, i, FALSE); + PUSHs(svp ? *svp : &PL_sv_undef); } } - else{ - XPUSHs(value ? value : &PL_sv_undef); + else if(flags & MOUSEf_TC_IS_HASHREF){ + HV* const hv = (HV*)SvRV(value); + HE* he; + + if(SvTYPE(hv) != SVt_PVHV){ + croak("Mouse-panic: Not a HASH reference"); + } + + hv_iterinit(hv); + while((he = hv_iternext(hv))){ + EXTEND(SP, 2); + PUSHs(hv_iterkeysv(he)); + PUSHs(hv_iterval(hv, he)); + } } PUTBACK; @@ -252,7 +246,7 @@ mouse_attr_get(pTHX_ SV* const self, MAGIC* const mg){ SV* const slot = MOUSE_mg_slot(mg); SV* value; - value = mouse_instance_get_slot(aTHX_ self, slot); + value = get_slot(self, slot); /* check_lazy */ if( !value && flags & MOUSEf_ATTR_IS_LAZY ){ @@ -282,10 +276,10 @@ mouse_attr_get(pTHX_ SV* const self, MAGIC* const mg){ } /* store value to slot */ - value = mouse_instance_set_slot(aTHX_ self, slot, value); + value = set_slot(self, slot, value); } - mouse_push_values(aTHX_ value, flags); + PUSH_VALUE(value, flags); } static void @@ -297,10 +291,10 @@ mouse_attr_set(pTHX_ SV* const self, MAGIC* const mg, SV* value){ value = mouse_apply_type_constraint(aTHX_ MOUSE_mg_xa(mg), value, flags); } - mouse_instance_set_slot(aTHX_ self, slot, value); + set_slot(self, slot, value); if(flags & MOUSEf_ATTR_IS_WEAK_REF){ - mouse_instance_weaken_slot(aTHX_ self, slot); + weaken_slot(self, slot); } if(flags & MOUSEf_ATTR_HAS_TRIGGER){ @@ -317,7 +311,7 @@ mouse_attr_set(pTHX_ SV* const self, MAGIC* const mg, SV* value){ /* need not SPAGAIN */ } - mouse_push_values(aTHX_ value, flags); + PUSH_VALUE(value, flags); } XS(mouse_xs_accessor) @@ -418,7 +412,7 @@ XS(mouse_xs_simple_reader) croak("Expected exactly one argument for a reader for '%"SVf"'", slot); } - value = mouse_instance_get_slot(aTHX_ self, slot); + value = get_slot(self, slot); ST(0) = value ? value : &PL_sv_undef; XSRETURN(1); } @@ -434,7 +428,7 @@ XS(mouse_xs_simple_writer) croak("Expected exactly two argument for a writer for '%"SVf"'", slot); } - ST(0) = mouse_instance_set_slot(aTHX_ self, slot, ST(1)); + ST(0) = set_slot(self, slot, ST(1)); XSRETURN(1); } @@ -449,7 +443,7 @@ XS(mouse_xs_simple_clearer) croak("Expected exactly one argument for a clearer for '%"SVf"'", slot); } - value = mouse_instance_delete_slot(aTHX_ self, slot); + value = delete_slot(self, slot); ST(0) = value ? value : &PL_sv_undef; XSRETURN(1); } @@ -464,11 +458,11 @@ XS(mouse_xs_simple_predicate) croak("Expected exactly one argument for a predicate for '%"SVf"'", slot); } - ST(0) = boolSV( mouse_instance_has_slot(aTHX_ self, slot) ); + ST(0) = boolSV( has_slot(self, slot) ); XSRETURN(1); } -/* simple instance slot accessor */ +/* simple instance slot accessor (or Mouse::Meta::Instance) */ SV* mouse_instance_create(pTHX_ HV* const stash) {