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=7cc9f349b4cca94942fc04d3abf11779bc78a583;hb=6423ed47a3392af0da9cd37ac8519583e51feb27;hpb=aa2d2e2c0621cdcb8b2ec7cf49beb3a9de11803c diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index 7cc9f34..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 */ @@ -72,10 +73,8 @@ mouse_class_has_custom_buildargs(pTHX_ HV* const stash) { XS(XS_Mouse__Object_BUILDARGS); /* prototype */ GV* const buildargs = gv_fetchmeth_autoload(stash, "BUILDARGS", sizeof("BUILDARGS")-1, 0); - CV* const cv = GvCV(buildargs); - assert(cv); - return CvXSUB(cv) == XS_Mouse__Object_BUILDARGS; + return buildargs && CvXSUB(GvCV(buildargs)) == XS_Mouse__Object_BUILDARGS; } static void @@ -104,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); @@ -173,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{ @@ -192,14 +197,8 @@ mouse_get_xc(pTHX_ SV* const metaclass) { return xc; } -AV* -mouse_get_all_attributes(pTHX_ SV* const metaclass) { - AV* const xc = mouse_get_xc(aTHX_ metaclass); - return MOUSE_xc_attrall(xc); -} - HV* -mouse_build_args(aTHX_ SV* metaclass, SV* const klass, I32 const start, I32 const items, I32 const ax) { +mouse_build_args(pTHX_ SV* metaclass, SV* const klass, I32 const start, I32 const items, I32 const ax) { HV* args; if((items - start) == 1){ SV* const args_ref = ST(start); @@ -213,8 +212,7 @@ mouse_build_args(aTHX_ SV* metaclass, SV* const klass, I32 const start, I32 cons else{ I32 i; - args = newHV(); - sv_2mortal((SV*)args); + args = newHV_mortal(); if( ((items - start) % 2) != 0 ){ if(!metaclass){ metaclass = get_metaclass(klass); } @@ -230,10 +228,75 @@ mouse_build_args(aTHX_ SV* metaclass, SV* const klass, I32 const start, I32 cons } void -mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const args, bool const invoke_triggers) { - AV* const xc = mouse_get_xc(aTHX_ meta); +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 len = AvFILLp(attrs) + 1; + I32 i; + AV* triggers_queue = NULL; - // TODO + ENTER; + SAVETMPS; + + if(!ignore_triggers){ + triggers_queue = newAV_mortal(); + } + + for(i = 0; i < len; 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 @@ -359,7 +422,8 @@ void get_all_attributes(SV* self) PPCODE: { - AV* const all_attrs = mouse_get_all_attributes(aTHX_ self); + AV* const xc = mouse_get_xc(aTHX_ self); + AV* const all_attrs = MOUSE_xc_attrall(xc); I32 const len = AvFILLp(all_attrs) + 1; I32 i; @@ -375,16 +439,17 @@ CODE: { HV* const args = mouse_build_args(aTHX_ meta, NULL, 1, items, ax); AV* const xc = mouse_get_xc(aTHX_ meta); + RETVAL = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc)); - mouse_class_initialize_object(aTHX_ meta, RETVAL, args, TRUE); + mouse_class_initialize_object(aTHX_ meta, RETVAL, args, FALSE); } void -_initialize_object_(SV* meta, SV* object, HV* args, bool invoke_triggers = TRUE) +_initialize_object(SV* meta, SV* object, HV* args, bool ignore_triggers = FALSE) CODE: { - mouse_class_initialize_object(aTHX_ meta, object, args, invoke_triggers); + mouse_class_initialize_object(aTHX_ meta, object, args, ignore_triggers); } MODULE = Mouse PACKAGE = Mouse::Meta::Role @@ -403,4 +468,3 @@ CODE: } OUTPUT: RETVAL -