X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs-src%2FMouseAttribute.xs;h=2caf7be54e9f34b4c1289486f43d9215e9919c93;hb=e69960297d0235c1213c75c5284e06875c1b46f2;hp=9bda4c64ec21a564497bfe6892fc413df075b993;hpb=0aad026606f2d1d5d27cfb8824dd182f790fa9e2;p=gitmo%2FMouse.git diff --git a/xs-src/MouseAttribute.xs b/xs-src/MouseAttribute.xs index 9bda4c6..2caf7be 100644 --- a/xs-src/MouseAttribute.xs +++ b/xs-src/MouseAttribute.xs @@ -35,6 +35,8 @@ mouse_get_xa(pTHX_ SV* const attr) { av_store(xa, MOUSE_XA_ATTRIBUTE, newSVsv(attr)); + av_store(xa, MOUSE_XA_INIT_ARG, newSVsv(mcall0s(attr, "init_arg"))); + if(predicate_calls(attr, "has_type_constraint")){ SV* tc; flags |= MOUSEf_ATTR_HAS_TC; @@ -71,13 +73,12 @@ mouse_get_xa(pTHX_ SV* const attr) { if(predicate_calls(attr, "is_lazy")){ flags |= MOUSEf_ATTR_IS_LAZY; - - if(predicate_calls(attr, "has_builder")){ - flags |= MOUSEf_ATTR_HAS_BUILDER; - } - else if(predicate_calls(attr, "has_default")){ - flags |= MOUSEf_ATTR_HAS_DEFAULT; - } + } + if(predicate_calls(attr, "has_builder")){ + flags |= MOUSEf_ATTR_HAS_BUILDER; + } + else if(predicate_calls(attr, "has_default")){ + flags |= MOUSEf_ATTR_HAS_DEFAULT; } if(predicate_calls(attr, "is_weak_ref")){ @@ -104,6 +105,75 @@ mouse_get_xa(pTHX_ SV* const attr) { return xa; } +SV* +mouse_xa_apply_type_constraint(pTHX_ AV* const xa, SV* value, U16 const flags){ + SV* const tc = MOUSE_xa_tc(xa); + SV* tc_code; + + if(flags & MOUSEf_ATTR_SHOULD_COERCE){ + value = mcall1s(tc, "coerce", value); + } + + if(!SvOK(MOUSE_xa_tc_code(xa))){ + tc_code = mcall0s(tc, "_compiled_type_constraint"); + av_store(xa, MOUSE_XA_TC_CODE, newSVsv(tc_code)); + + if(!IsCodeRef(tc_code)){ + mouse_throw_error(MOUSE_xa_attribute(xa), tc, "Not a CODE reference"); + } + } + else{ + tc_code = MOUSE_xa_tc_code(xa); + } + + if(!mouse_tc_check(aTHX_ tc_code, value)){ + mouse_throw_error(MOUSE_xa_attribute(xa), value, + "Attribute (%"SVf") does not pass the type constraint because: %"SVf, + mcall0(MOUSE_xa_attribute(xa), mouse_name), + mcall1s(tc, "get_message", value)); + } + + return value; +} + + +SV* +mouse_xa_set_default(pTHX_ AV* const xa, SV* const object) { + U16 const flags = (U16)MOUSE_xa_flags(xa); + SV* value; + + ENTER; + SAVETMPS; + + /* get default value by $attr->builder or $attr->default */ + if(flags & MOUSEf_ATTR_HAS_BUILDER){ + SV* const builder = mcall0s(MOUSE_xa_attribute(xa), "builder"); + value = mcall0(object, builder); /* $object->$builder() */ + } + else { + value = mcall0s(MOUSE_xa_attribute(xa), "default"); + + if(IsCodeRef(value)){ + value = mcall0(object, value); + } + } + + /* apply coerce and type constraint */ + if(flags & MOUSEf_ATTR_HAS_TC){ + value = mouse_xa_apply_type_constraint(aTHX_ xa, value, flags); + } + + /* store value to slot */ + value = set_slot(object, MOUSE_xa_slot(xa), value); + if(flags & MOUSEf_ATTR_IS_WEAK_REF && SvROK(value)){ + weaken_slot(object, MOUSE_xa_slot(xa)); + } + + FREETMPS; + LEAVE; + + return value; +} MODULE = Mouse::Meta::Attribute PACKAGE = Mouse::Meta::Attribute @@ -148,6 +218,5 @@ BOOT: INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_builder, builder); INSTALL_SIMPLE_PREDICATE_WITH_KEY(Attribute, has_documentation, documentation); - newCONSTSUB(gv_stashpvs("Mouse::Meta::Attribute", TRUE), "accessor_metaclass", - newSVpvs("Mouse::Meta::Method::Accessor::XS")); + INSTALL_CLASS_HOLDER(Attribute, accessor_metaclass, "Mouse::Meta::Method::Accessor::XS");