X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMouse.git;a=blobdiff_plain;f=xs-src%2FMouse.xs;h=b16720606508e362da172e1c3f3891f8e7d8ff86;hp=bec3c7d18c5caf0da1529288c7e6073b08367a68;hb=6423ed47a3392af0da9cd37ac8519583e51feb27;hpb=0aad026606f2d1d5d27cfb8824dd182f790fa9e2 diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index bec3c7d..b167206 100644 --- a/xs-src/Mouse.xs +++ b/xs-src/Mouse.xs @@ -8,7 +8,7 @@ SV* mouse_name; SV* mouse_get_attribute; SV* mouse_get_attribute_list; - +#define MOUSE_xc_flags(a) SvUVX(MOUSE_av_at((a), MOUSE_XC_FLAGS)) #define MOUSE_xc_gen(a) MOUSE_av_at((a), MOUSE_XC_GEN) #define MOUSE_xc_stash(a) ( (HV*)MOUSE_av_at((a), MOUSE_XC_STASH) ) #define MOUSE_xc_attrall(a) ( (AV*)MOUSE_av_at((a), MOUSE_XC_ATTRALL) ) @@ -25,9 +25,10 @@ enum mouse_xc_flags_t { /* Mouse XS Metaclass object */ enum mouse_xc_ix_t{ + MOUSE_XC_FLAGS, + MOUSE_XC_GEN, /* class generation */ MOUSE_XC_STASH, /* symbol table hash */ - MOUSE_XC_FLAGS, MOUSE_XC_BUILDARGS, /* Custom BUILDARGS */ @@ -102,14 +103,19 @@ mouse_class_update_xc(pTHX_ SV* const metaclass PERL_UNUSED_DECL, HV* const stas /* update */ - if(SvTRUEx( mcall0s(metaclass, "is_immutable") )){ + if(predicate_calls(metaclass, "is_immutable")){ flags |= MOUSEf_XC_IS_IMMUTABLE; } + if(predicate_calls(metaclass, "is_anon_class")){ + flags |= MOUSEf_XC_IS_ANON; + } + if(mouse_class_has_custom_buildargs(aTHX_ stash)){ flags |= MOUSEf_XC_HAS_BUILDARGS; } + av_store(xc, MOUSE_XC_FLAGS, newSVuv(flags)); av_store(xc, MOUSE_XC_ATTRALL, (SV*)attrall); av_store(xc, MOUSE_XC_BUILDALL, (SV*)buildall); av_store(xc, MOUSE_XC_DEMOLISHALL, (SV*)demolishall); @@ -171,6 +177,7 @@ mouse_get_xc(pTHX_ SV* const metaclass) { av_store(xc, MOUSE_XC_GEN, newSViv(0)); av_store(xc, MOUSE_XC_STASH, (SV*)stash); + SvREFCNT_inc_simple_void_NN(stash); } else{ @@ -224,13 +231,72 @@ void mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const args, bool const ignore_triggers) { AV* const xc = mouse_get_xc(aTHX_ meta); AV* const attrs = MOUSE_xc_attrall(xc); - I32 const len = AvFILLp(attrs) + 1; + I32 len = AvFILLp(attrs) + 1; I32 i; - AV* const triggers_queue = (ignore_triggers ? NULL : newAV_mortal()); + AV* triggers_queue = NULL; + + ENTER; + SAVETMPS; + + if(!ignore_triggers){ + triggers_queue = newAV_mortal(); + } for(i = 0; i < len; i++){ - AV* const xa = mouse_get_xa(aTHX_ AvARRAY(attrs)[i]); + SV* const attr = AvARRAY(attrs)[i]; + AV* const xa = mouse_get_xa(aTHX_ AvARRAY(attrs)[i]); + + SV* const slot = MOUSE_xa_slot(xa); + U16 const flags = (U16)MOUSE_xa_flags(xa); + SV* const init_arg = MOUSE_xa_init_arg(xa); + HE* he; + + if(SvOK(init_arg) && ( he = hv_fetch_ent(args, init_arg, FALSE, 0U) ) ){ + SV* value = HeVAL(he); + if(flags & MOUSEf_ATTR_HAS_TC){ + value = mouse_xa_apply_type_constraint(aTHX_ xa, value, flags); + } + set_slot(object, slot, value); + if(SvROK(value) && flags & MOUSEf_ATTR_IS_WEAK_REF){ + weaken_slot(object, slot); + } + if(flags & MOUSEf_ATTR_HAS_TRIGGER && triggers_queue){ + AV* const pair = newAV(); + av_push(pair, newSVsv( mcall0s(attr, "trigger") )); + av_push(pair, newSVsv(value)); + + av_push(triggers_queue, (SV*)pair); + } + } + else { /* no init arg */ + if(flags & (MOUSEf_ATTR_HAS_DEFAULT | MOUSEf_ATTR_HAS_BUILDER)){ + if(!(flags & MOUSEf_ATTR_IS_LAZY)){ + mouse_xa_set_default(aTHX_ xa, object); + } + } + else if(flags & MOUSEf_ATTR_IS_REQUIRED) { + mouse_throw_error(attr, NULL, "Attribute (%"SVf") is required", slot); + } + } + } /* for each attributes */ + + if(triggers_queue){ + len = AvFILLp(triggers_queue) + 1; + for(i = 0; i < len; i++){ + AV* const pair = (AV*)AvARRAY(triggers_queue)[i]; + SV* const trigger = AvARRAY(pair)[0]; + SV* const value = AvARRAY(pair)[1]; + + mcall1(object, trigger, value); + } } + + if(MOUSE_xc_flags(xc) & MOUSEf_XC_IS_ANON){ + set_slot(object, newSVpvs_flags("__ANON__", SVs_TEMP), meta); + } + + FREETMPS; + LEAVE; } MODULE = Mouse PACKAGE = Mouse @@ -380,7 +446,7 @@ CODE: void -_initialize_object_(SV* meta, SV* object, HV* args, bool ignore_triggers = FALSE) +_initialize_object(SV* meta, SV* object, HV* args, bool ignore_triggers = FALSE) CODE: { mouse_class_initialize_object(aTHX_ meta, object, args, ignore_triggers); @@ -402,4 +468,3 @@ CODE: } OUTPUT: RETVAL -