X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs-src%2FMouse.xs;h=efd1e94a5996a1cdf73a24e4901145aa5b903e26;hb=6e1e48894362f20aeb63ccc0e1b963c7e1d7cf81;hp=8033635bc0a83b88544657a79cca5e43c082e71a;hpb=13b9990881cb1c765a47711fc4eb0d47a404c756;p=gitmo%2FMouse.git diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index 8033635..efd1e94 100644 --- a/xs-src/Mouse.xs +++ b/xs-src/Mouse.xs @@ -76,10 +76,10 @@ mouse_class_push_attribute_list(pTHX_ SV* const metaclass, AV* const attrall, HV } } +XS(XS_Mouse__Object_BUILDARGS); /* prototype */ + static int 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); return buildargs && CvXSUB(GvCV(buildargs)) != XS_Mouse__Object_BUILDARGS; @@ -123,7 +123,7 @@ mouse_class_update_xc(pTHX_ SV* const metaclass PERL_UNUSED_DECL, HV* const stas flags |= MOUSEf_XC_HAS_BUILDARGS; } - if(predicate_calls(metaclass, "__strict_constructor")){ + if(predicate_calls(metaclass, "strict_constructor")){ flags |= MOUSEf_XC_CONSTRUCTOR_IS_STRICT; } @@ -297,7 +297,7 @@ mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const I32 const len = AvFILLp(attrs) + 1; I32 i; AV* triggers_queue = NULL; - I32 used = 0; + U32 used = 0; assert(meta || object); assert(args); @@ -445,6 +445,11 @@ mouse_get_modifier_storage(pTHX_ return (AV*)SvRV(storage_ref); } +DECL_BOOT(Mouse__Util); +DECL_BOOT(Mouse__Util__TypeConstraints); +DECL_BOOT(Mouse__Meta__Method__Accessor__XS); +DECL_BOOT(Mouse__Meta__Attribute); + MODULE = Mouse PACKAGE = Mouse PROTOTYPES: DISABLE @@ -459,10 +464,10 @@ BOOT: mouse_get_attribute = newSVpvs_share("get_attribute"); mouse_get_attribute_list = newSVpvs_share("get_attribute_list"); - MOUSE_CALL_BOOT(Mouse__Util); - MOUSE_CALL_BOOT(Mouse__Util__TypeConstraints); - MOUSE_CALL_BOOT(Mouse__Meta__Method__Accessor__XS); - MOUSE_CALL_BOOT(Mouse__Meta__Attribute); + CALL_BOOT(Mouse__Util); + CALL_BOOT(Mouse__Util__TypeConstraints); + CALL_BOOT(Mouse__Meta__Method__Accessor__XS); + CALL_BOOT(Mouse__Meta__Attribute); MODULE = Mouse PACKAGE = Mouse::Meta::Module @@ -524,7 +529,6 @@ 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_SIMPLE_READER_WITH_KEY(Class, __strict_constructor, strict_constructor); INSTALL_CLASS_HOLDER(Class, method_metaclass, "Mouse::Meta::Method"); INSTALL_CLASS_HOLDER(Class, attribute_metaclass, "Mouse::Meta::Attribute"); @@ -536,7 +540,6 @@ BOOT: newCONSTSUB(gv_stashpvs("Mouse::Meta::Method::Destructor::XS", TRUE), "_generate_destructor", newRV_inc((SV*)get_cvs("Mouse::Object::DESTROY", TRUE))); - void linearized_isa(SV* self) PPCODE: @@ -571,26 +574,28 @@ PPCODE: } } -SV* +void new_object(SV* meta, ...) CODE: { AV* const xc = mouse_get_xc(aTHX_ meta); HV* const args = mouse_buildargs(aTHX_ meta, NULL, ax, items); + SV* object; - RETVAL = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc)); - mouse_class_initialize_object(aTHX_ meta, RETVAL, args, FALSE); - mouse_buildall(aTHX_ xc, RETVAL, sv_2mortal(newRV_inc((SV*)args))); /* BUILDALL */ + object = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc)); + mouse_class_initialize_object(aTHX_ meta, object, args, FALSE); + mouse_buildall(aTHX_ xc, object, sv_2mortal(newRV_inc((SV*)args))); /* BUILDALL */ + ST(0) = object; /* because object is mortal, we should return it as is */ + XSRETURN(1); } -OUTPUT: - RETVAL -SV* +void clone_object(SV* meta, SV* object, ...) CODE: { AV* const xc = mouse_get_xc(aTHX_ meta); HV* const args = mouse_buildargs(aTHX_ meta, NULL, ax + 1, items - 1); + SV* proto; if(!mouse_is_an_instance_of(aTHX_ MOUSE_xc_stash(xc), object)) { mouse_throw_error(meta, object, @@ -598,12 +603,11 @@ CODE: mcall0(meta, mouse_name), object); } - RETVAL = mouse_instance_clone(aTHX_ object); - mouse_class_initialize_object(aTHX_ meta, RETVAL, args, TRUE); + proto = mouse_instance_clone(aTHX_ object); + mouse_class_initialize_object(aTHX_ meta, proto, args, TRUE); + ST(0) = proto; /* because object is mortal, we should return it as is */ + XSRETURN(1); } -OUTPUT: - RETVAL - void _initialize_object(SV* meta, SV* object, HV* args, bool is_cloning = FALSE) @@ -612,6 +616,45 @@ CODE: mouse_class_initialize_object(aTHX_ meta, object, args, is_cloning); } +void +strict_constructor(SV* self, SV* value = NULL) +CODE: +{ + SV* const slot = sv_2mortal(newSVpvs_share("strict_constructor")); + SV* const stash_ref = mcall0(self, mouse_namespace); + HV* stash; + + if(!(SvROK(stash_ref) && SvTYPE(SvRV(stash_ref)) == SVt_PVHV)) { + croak("namespace() didn't return a HASH reference"); + } + stash = (HV*)SvRV(stash_ref); + + if(value) { /* setter */ + set_slot(self, slot, value); + mro_method_changed_in(stash); + } + + value = get_slot(self, slot); + + if(!value) { + AV* const isa = mro_get_linear_isa(stash); + I32 const len = av_len(isa) + 1; + I32 i; + for(i = 1; i < len; i++) { + SV* const klass = MOUSE_av_at(isa, i); + SV* const meta = get_metaclass(klass); + if(!SvOK(meta)){ + continue; /* skip non-Mouse classes */ + } + value = get_slot(meta, slot); + if(value) { + break; + } + } + } + ST(0) = value ? value : &PL_sv_no; +} + MODULE = Mouse PACKAGE = Mouse::Meta::Role BOOT: @@ -624,7 +667,7 @@ void add_before_modifier(SV* self, SV* name, SV* modifier) CODE: { - av_push(mouse_get_modifier_storage(aTHX_ self, ix, name), newSVsv(modifier)); + av_push(mouse_get_modifier_storage(aTHX_ self, (enum mouse_modifier_t)ix, name), newSVsv(modifier)); } ALIAS: add_before_method_modifier = MOUSE_M_BEFORE @@ -639,7 +682,7 @@ ALIAS: get_after_method_modifiers = MOUSE_M_AFTER PPCODE: { - AV* const storage = mouse_get_modifier_storage(aTHX_ self, ix, name); + AV* const storage = mouse_get_modifier_storage(aTHX_ self, (enum mouse_modifier_t)ix, name); I32 const len = av_len(storage) + 1; if(GIMME_V == G_ARRAY) { I32 i; @@ -655,7 +698,7 @@ PPCODE: MODULE = Mouse PACKAGE = Mouse::Object -SV* +void new(SV* klass, ...) CODE: { @@ -663,6 +706,7 @@ CODE: AV* const xc = mouse_get_xc(aTHX_ meta); UV const flags = MOUSE_xc_flags(xc); SV* args; + SV* object; /* BUILDARGS */ if(flags & MOUSEf_XC_HAS_BUILDARGS){ @@ -692,12 +736,12 @@ CODE: } /* new_object */ - RETVAL = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc)); - mouse_class_initialize_object(aTHX_ meta, RETVAL, (HV*)SvRV(args), FALSE); - mouse_buildall(aTHX_ xc, RETVAL, args); /* BUILDALL */ + object = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc)); + mouse_class_initialize_object(aTHX_ meta, object, (HV*)SvRV(args), FALSE); + mouse_buildall(aTHX_ xc, object, args); /* BUILDALL */ + ST(0) = object; /* because object is mortal, we should return it as is */ + XSRETURN(1); } -OUTPUT: - RETVAL void DESTROY(SV* object)