sub ClassName { Mouse::Util::is_class_loaded($_[0]) }
sub RoleName { (Mouse::Util::class_of($_[0]) || return 0)->isa('Mouse::Meta::Role') }
+sub _parameterize_ArrayRef_for {
+ my($type_parameter) = @_;
+ my $check = $type_parameter->_compiled_type_constraint;
+
+ return sub {
+ foreach my $value (@{$_}) {
+ return undef unless $check->($value);
+ }
+ return 1;
+ }
+}
+
+sub _parameterize_HashRef_for {
+ my($type_parameter) = @_;
+ my $check = $type_parameter->_compiled_type_constraint;
+
+ return sub {
+ foreach my $value(values %{$_}){
+ return undef unless $check->($value);
+ }
+ return 1;
+ };
+}
+
+# 'Maybe' type accepts 'Any', so it requires parameters
+sub _parameterize_Maybe_for {
+ my($type_parameter) = @_;
+ my $check = $type_parameter->_compiled_type_constraint;
+
+ return sub{
+ return !defined($_) || $check->($_);
+ };
+};
+
+
package
Mouse::Meta::Module;
}
}
-$TYPE{ArrayRef}{constraint_generator} = sub {
- my($type_parameter) = @_;
- my $check = $type_parameter->_compiled_type_constraint;
-
- return sub{
- foreach my $value (@{$_}) {
- return undef unless $check->($value);
- }
- return 1;
- }
-};
-$TYPE{HashRef}{constraint_generator} = sub {
- my($type_parameter) = @_;
- my $check = $type_parameter->_compiled_type_constraint;
-
- return sub{
- foreach my $value(values %{$_}){
- return undef unless $check->($value);
- }
- return 1;
- };
-};
-
-# 'Maybe' type accepts 'Any', so it requires parameters
-$TYPE{Maybe}{constraint_generator} = sub {
- my($type_parameter) = @_;
- my $check = $type_parameter->_compiled_type_constraint;
-
- return sub{
- return !defined($_) || $check->($_);
- };
-};
+$TYPE{ArrayRef}{constraint_generator} = \&_parameterize_ArrayRef_for;
+$TYPE{HashRef}{constraint_generator} = \&_parameterize_HashRef_for;
+$TYPE{Maybe}{constraint_generator} = \&_parameterize_Maybe_for;
sub _find_or_create_parameterized_type{
my($base, $param) = @_;
return SvROK(sv) && SvOBJECT(SvRV(sv)) && !SvRXOK(sv);
}
+/* Parameterized type constraints */
+
+int
+mouse_parameterized_ArrayRef(pTHX_ SV* const param, SV* const sv) {
+ if(mouse_tc_ArrayRef(aTHX_ sv)){
+ AV* const av = (AV*)SvRV(sv);
+ I32 const len = av_len(av) + 1;
+ I32 i;
+ for(i = 0; i < len; i++){
+ SV* const value = *av_fetch(av, i, TRUE);
+ SvGETMAGIC(value);
+ if(!mouse_tc_check(aTHX_ param, value)){
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int
+mouse_parameterized_HashRef(pTHX_ SV* const param, SV* const sv) {
+ if(mouse_tc_HashRef(aTHX_ sv)){
+ HV* const hv = (HV*)SvRV(sv);
+ HE* he;
+
+ hv_iterinit(hv);
+ while((he = hv_iternext(hv))){
+ SV* const value = hv_iterval(hv, he);
+ SvGETMAGIC(value);
+ if(!mouse_tc_check(aTHX_ param, value)){
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int
+mouse_parameterized_Maybe(pTHX_ SV* const param, SV* const sv) {
+ if(SvOK(sv)){
+ return mouse_tc_check(aTHX_ param, sv);
+ }
+ return TRUE;
+}
+
/*
* This class_type generator is taken from Scalar::Util::Instance
*/
static MGVTBL mouse_util_type_constraints_vtbl; /* not used, only for identity */
-CV*
+static CV*
mouse_tc_parameterize(pTHX_ const char* const name, check_fptr_t const fptr, SV* const param) {
- CV* const xsub = newXS(name, XS_Mouse_parameterized_check, __FILE__);
+ CV* xsub;
+ xsub = newXS(name, XS_Mouse_parameterized_check, __FILE__);
CvXSUBANY(xsub).any_ptr = sv_magicext(
(SV*)xsub,
param, /* mg_obj: refcnt will be increased */
XSRETURN(1);
+CV*
+_parameterize_ArrayRef_for(SV* param)
+ALIAS:
+ _parameterize_ArrayRef_for = MOUSE_TC_ARRAY_REF
+ _parameterize_HashRef_for = MOUSE_TC_HASH_REF
+ _parameterize_Maybe_for = MOUSE_TC_MAYBE
+CODE:
+{
+ check_fptr_t fptr;
+ SV* const tc_code = mcall0s(param, "_compiled_type_constraint");
+ if(!(SvROK(tc_code) && SvTYPE(SvRV(tc_code)) == SVt_PVCV)){
+ croak("_compiled_type_constraint didn't return a CODE reference");
+ }
+
+ switch(ix){
+ case MOUSE_TC_ARRAY_REF:
+ fptr = mouse_parameterized_ArrayRef;
+ break;
+ case MOUSE_TC_HASH_REF:
+ fptr = mouse_parameterized_HashRef;
+ break;
+ default: /* Maybe type */
+ fptr = mouse_parameterized_Maybe;
+ }
+ RETVAL = mouse_tc_parameterize(aTHX_ NULL, fptr, tc_code);
+}
+OUTPUT:
+ RETVAL
+