X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMouse.git;a=blobdiff_plain;f=xs-src%2FMouse.xs;h=0a7d3f9030ce05e176ef949cc04924a459f70983;hp=d7cdb78dd6b740e0621b18eeeb3b02b67b67dd2c;hb=ca8e67d622c1a14bee4933ad64b1e465c5d63766;hpb=f8beb873dc6db9067aacdada68d0158366570f28 diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index d7cdb78..0a7d3f9 100644 --- a/xs-src/Mouse.xs +++ b/xs-src/Mouse.xs @@ -249,8 +249,9 @@ mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const assert(args); assert(SvTYPE(args) == SVt_PVHV); - ENTER; - SAVETMPS; + if(mg_find((SV*)args, PERL_MAGIC_tied)){ + croak("You cannot use tied HASH reference as initializing arguments"); + } if(!ignore_triggers){ triggers_queue = newAV_mortal(); @@ -270,7 +271,7 @@ mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const if(flags & MOUSEf_ATTR_HAS_TC){ value = mouse_xa_apply_type_constraint(aTHX_ xa, value, flags); } - set_slot(object, slot, value); + value = set_slot(object, slot, value); if(SvROK(value) && flags & MOUSEf_ATTR_IS_WEAK_REF){ weaken_slot(object, slot); } @@ -306,11 +307,9 @@ mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const } if(MOUSE_xc_flags(xc) & MOUSEf_XC_IS_ANON){ - set_slot(object, newSVpvs_flags("__METACLASS__", SVs_TEMP), meta); + (void)set_slot(object, newSVpvs_flags("__METACLASS__", SVs_TEMP), meta); } - FREETMPS; - LEAVE; } static SV* @@ -335,6 +334,29 @@ mouse_initialize_metaclass(pTHX_ SV* const klass) { return meta; } +static void +mouse_buildall(pTHX_ AV* const xc, SV* const object, SV* const args) { + AV* const buildall = MOUSE_xc_buildall(xc); + I32 const len = AvFILLp(buildall) + 1; + I32 i; + for(i = 0; i < len; i++){ + dSP; + + PUSHMARK(SP); + EXTEND(SP, 2); + PUSHs(object); + PUSHs(args); + PUTBACK; + + call_sv(AvARRAY(buildall)[i], G_VOID); + + /* discard a scalar which G_VOID returns */ + SPAGAIN; + (void)POPs; + PUTBACK; + } +} + MODULE = Mouse PACKAGE = Mouse PROTOTYPES: DISABLE @@ -417,7 +439,7 @@ CODE: } sv_setsv_mg((SV*)gv, code_ref); /* *gv = $code_ref */ - set_slot(methods, name, code); /* $self->{methods}{$name} = $code */ + (void)set_slot(methods, name, code); /* $self->{methods}{$name} = $code */ /* name the CODE ref if it's anonymous */ { @@ -436,6 +458,7 @@ MODULE = Mouse PACKAGE = Mouse::Meta::Class BOOT: INSTALL_SIMPLE_READER(Class, roles); INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id); + INSTALL_SIMPLE_READER(Class, is_immutable); INSTALL_CLASS_HOLDER(Class, method_metaclass, "Mouse::Meta::Method"); INSTALL_CLASS_HOLDER(Class, attribute_metaclass, "Mouse::Meta::Attribute"); @@ -520,11 +543,10 @@ CODE: AV* const xc = mouse_get_xc(aTHX_ meta); UV const flags = MOUSE_xc_flags(xc); SV* args; - AV* buildall; - I32 len, i; /* BUILDARGS */ if(flags & MOUSEf_XC_HAS_BUILDARGS){ + I32 i; SPAGAIN; PUSHMARK(SP); @@ -552,26 +574,16 @@ CODE: RETVAL = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc)); mouse_class_initialize_object(aTHX_ meta, RETVAL, (HV*)SvRV(args), FALSE); - /* BUILDALL */ - buildall = MOUSE_xc_buildall(xc); - len = AvFILLp(buildall) + 1; - for(i = 0; i < len; i++){ - dSP; - - PUSHMARK(SP); - EXTEND(SP, 2); - PUSHs(RETVAL); /* self */ - PUSHs(args); - PUTBACK; - - call_sv(AvARRAY(buildall)[i], G_VOID | G_DISCARD); - } + mouse_buildall(aTHX_ xc, RETVAL, args); } OUTPUT: RETVAL void DESTROY(SV* object) +ALIAS: + DESTROY = 0 + DEMOLISHALL = 1 CODE: { SV* const meta = get_metaclass(object); @@ -579,7 +591,8 @@ CODE: I32 len, i; if(!IsObject(object)){ - croak("You must not call DESTROY as a class method"); + croak("You must not call %s as a class method", + ix == 0 ? "DESTROY" : "DEMOLISHALL"); } if(SvOK(meta)){ @@ -587,7 +600,7 @@ CODE: demolishall = MOUSE_xc_demolishall(xc); } - else { + else { /* The metaclass is already destroyed */ AV* const linearized_isa = mro_get_linear_isa(SvSTASH(SvRV(object))); len = AvFILLp(linearized_isa) + 1; @@ -603,7 +616,6 @@ CODE: } } - /* DEMOLISHALL */ len = AvFILLp(demolishall) + 1; if(len > 0){ GV* const statusvalue = gv_fetchpvs("?", 0, SVt_PV); @@ -619,8 +631,14 @@ CODE: XPUSHs(object); PUTBACK; - call_sv(AvARRAY(demolishall)[i], G_VOID | G_DISCARD | G_EVAL); - if(SvTRUE(ERRSV)){ + call_sv(AvARRAY(demolishall)[i], G_VOID | G_EVAL); + + /* discard a scalar which G_VOID returns */ + SPAGAIN; + (void)POPs; + PUTBACK; + + if(sv_true(ERRSV)){ SV* const e = newSVsv(ERRSV); FREETMPS; @@ -644,3 +662,15 @@ OUTPUT: RETVAL +void +BUILDALL(SV* self, SV* args) +CODE: +{ + SV* const meta = get_metaclass(self); + AV* const xc = mouse_get_xc(aTHX_ meta); + + if(!IsHashRef(args)){ + croak("You must pass a HASH reference to BUILDALL"); + } + mouse_buildall(aTHX_ xc, self, args); +}