Make some constants as class attributes
gfx [Tue, 17 Nov 2009 02:15:05 +0000 (11:15 +0900)]
lib/Mouse/Meta/Class.pm
lib/Mouse/Meta/Role.pm
lib/Mouse/PurePerl.pm
mouse.h
xs-src/Mouse.xs
xs-src/MouseAccessor.xs
xs-src/MouseAttribute.xs

index ae69e32..99e0c6d 100644 (file)
@@ -6,11 +6,11 @@ use Scalar::Util qw/blessed weaken/;
 use Mouse::Meta::Module;
 our @ISA = qw(Mouse::Meta::Module);
 
-sub method_metaclass()    { 'Mouse::Meta::Method'    }
-sub attribute_metaclass() { 'Mouse::Meta::Attribute' }
+sub method_metaclass;
+sub attribute_metaclass;
 
-sub constructor_class();
-sub destructor_class();
+sub constructor_class;
+sub destructor_class;
 
 sub _construct_meta {
     my($class, %args) = @_;
index 225ed0b..620baf0 100644 (file)
@@ -4,7 +4,7 @@ use Mouse::Util qw(:meta not_supported english_list); # enables strict and warni
 use Mouse::Meta::Module;
 our @ISA = qw(Mouse::Meta::Module);
 
-sub method_metaclass(){ 'Mouse::Meta::Role::Method' } # required for get_method()
+sub method_metaclass;
 
 sub _construct_meta {
     my $class = shift;
index 1ce720d..470fbd7 100644 (file)
@@ -203,8 +203,11 @@ sub add_method {
 package
     Mouse::Meta::Class;
 
-sub constructor_class() { 'Mouse::Meta::Method::Constructor' }
-sub destructor_class()  { 'Mouse::Meta::Method::Destructor'  }
+sub method_metaclass    { $_[0]->{method_metaclass}    || 'Mouse::Meta::Method'    }
+sub attribute_metaclass { $_[0]->{attribute_metaclass} || 'Mouse::Meta::Attribute' }
+
+sub constructor_class { $_[0]->{constructor_class} || 'Mouse::Meta::Method::Constructor' }
+sub destructor_class  { $_[0]->{destructor_class}  || 'Mouse::Meta::Method::Destructor'  }
 
 sub is_anon_class{
     return exists $_[0]->{anon_serial_id};
@@ -278,6 +281,8 @@ sub _initialize_object{
 package
     Mouse::Meta::Role;
 
+sub method_metaclass{ $_[0]->{method_metaclass} || 'Mouse::Meta::Role::Method' }
+
 sub is_anon_role{
     return exists $_[0]->{anon_serial_id};
 }
@@ -287,7 +292,9 @@ sub get_roles { $_[0]->{roles} }
 package
     Mouse::Meta::Attribute;
 
-use Mouse::Meta::Method::Accessor;
+require Mouse::Meta::Method::Accessor;
+
+sub accessor_metaclass{ $_[0]->{accessor_metaclass} || 'Mouse::Meta::Method::Accessor' }
 
 # readers
 
@@ -333,8 +340,6 @@ sub has_builder          { exists $_[0]->{builder}         }
 
 sub has_documentation    { exists $_[0]->{documentation}   }
 
-sub accessor_metaclass(){ 'Mouse::Meta::Method::Accessor' }
-
 package
     Mouse::Meta::TypeConstraint;
 
diff --git a/mouse.h b/mouse.h
index 9d86675..8be21a4 100644 (file)
--- a/mouse.h
+++ b/mouse.h
@@ -141,16 +141,26 @@ void mouse_instance_weaken_slot(pTHX_ SV* const instance, SV* const slot);
 #define set_slots(self, key, value) set_slot(self, sv_2mortal(newSVpvs_share(key)), value)
 
 /* mouse_simle_accessor.xs */
-#define INSTALL_SIMPLE_READER(klass, name)                  INSTALL_SIMPLE_READER_WITH_KEY(klass, name, name)
-#define INSTALL_SIMPLE_READER_WITH_KEY(klass, name, key)    (void)mouse_install_simple_accessor(aTHX_ "Mouse::Meta::" #klass "::" #name, #key, sizeof(#key)-1, XS_Mouse_simple_reader)
-
-#define INSTALL_SIMPLE_WRITER(klass, name)                  INSTALL_SIMPLE_WRITER_WITH_KEY(klass, name, name)
-#define INSTALL_SIMPLE_WRITER_WITH_KEY(klass, name, key)    (void)mouse_install_simple_accessor(aTHX_ "Mouse::Meta::" #klass "::" #name, #key, sizeof(#key)-1, XS_Mouse_simple_writer)
-
-#define INSTALL_SIMPLE_PREDICATE(klass, name)                INSTALL_SIMPLE_PREDICATE_WITH_KEY(klass, name, name)
-#define INSTALL_SIMPLE_PREDICATE_WITH_KEY(klass, name, key) (void)mouse_install_simple_accessor(aTHX_ "Mouse::Meta::" #klass "::" #name, #key, sizeof(#key)-1, XS_Mouse_simple_predicate)
-
-CV* mouse_install_simple_accessor(pTHX_ const char* const fq_name, const char* const key, I32 const keylen, XSUBADDR_t const accessor_impl);
+#define INSTALL_SIMPLE_READER(klass, name) \
+    INSTALL_SIMPLE_READER_WITH_KEY(klass, name, name)
+#define INSTALL_SIMPLE_READER_WITH_KEY(klass, name, key) \
+    (void)mouse_install_simple_accessor(aTHX_ "Mouse::Meta::" #klass "::" #name, #key, sizeof(#key)-1, XS_Mouse_simple_reader, NULL, 0)
+#define INSTALL_SIMPLE_READER_WITH_DEFAULTSV(klass, name, dsv) \
+    (void)mouse_install_simple_accessor(aTHX_ "Mouse::Meta::" #klass "::" #name, #name, sizeof(#name)-1, XS_Mouse_simple_reader, (dsv), HEf_SVKEY)
+#define INSTALL_SIMPLE_READER_WITH_DEFAULTS(klass, name, ds) \
+    INSTALL_SIMPLE_READER_WITH_DEFAULTSV(klass, name, newSVpvs(ds))
+
+#define INSTALL_SIMPLE_WRITER(klass, name) \
+    NSTALL_SIMPLE_WRITER_WITH_KEY(klass, name, name)
+#define INSTALL_SIMPLE_WRITER_WITH_KEY(klass, name, key) \
+    (void)mouse_install_simple_accessor(aTHX_ "Mouse::Meta::" #klass "::" #name, #key, sizeof(#key)-1, XS_Mouse_simple_writer, NULL, 0)
+
+#define INSTALL_SIMPLE_PREDICATE(klass, name) \
+    INSTALL_SIMPLE_PREDICATE_WITH_KEY(klass, name, name)
+#define INSTALL_SIMPLE_PREDICATE_WITH_KEY(klass, name, key) \
+    (void)mouse_install_simple_accessor(aTHX_ "Mouse::Meta::" #klass "::" #name, #key, sizeof(#key)-1, XS_Mouse_simple_predicate, NULL, 0)
+
+CV* mouse_install_simple_accessor(pTHX_ const char* const fq_name, const char* const key, I32 const keylen, XSUBADDR_t const accessor_impl, void* const dptr, I32 const dlen);
 
 XS(XS_Mouse_simple_reader);
 XS(XS_Mouse_simple_writer);
index 27f871c..fba5778 100644 (file)
@@ -436,11 +436,11 @@ MODULE = Mouse  PACKAGE = Mouse::Meta::Class
 BOOT:
     INSTALL_SIMPLE_READER(Class, roles);
     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id);
-    newCONSTSUB(gv_stashpvs("Mouse::Meta::Class", TRUE), "constructor_class",
-        newSVpvs("Mouse::Meta::Method::Constructor::XS"));
-    newCONSTSUB(gv_stashpvs("Mouse::Meta::Class", TRUE), "destructor_class",
-        newSVpvs("Mouse::Meta::Method::Destructor::XS"));
 
+    INSTALL_SIMPLE_READER_WITH_DEFAULTS(Class, method_metaclass,     "Mouse::Meta::Method");
+    INSTALL_SIMPLE_READER_WITH_DEFAULTS(Class, attribute_metaclass,  "Mouse::Meta::Attribute");
+    INSTALL_SIMPLE_READER_WITH_DEFAULTS(Class, constructor_class,    "Mouse::Meta::Method::Constructor::XS");
+    INSTALL_SIMPLE_READER_WITH_DEFAULTS(Class, destructor_class,     "Mouse::Meta::Method::Destructor::XS");
 
     newCONSTSUB(gv_stashpvs("Mouse::Meta::Method::Constructor::XS", TRUE), "_generate_constructor",
         newRV_inc((SV*)get_cvs("Mouse::Object::new", TRUE)));
@@ -517,6 +517,8 @@ BOOT:
     INSTALL_SIMPLE_READER_WITH_KEY(Role, get_roles, roles);
     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Role, is_anon_role, anon_serial_id);
 
+    INSTALL_SIMPLE_READER_WITH_DEFAULTS(Role, method_metaclass,  "Mouse::Meta::Role::Method");
+
 MODULE = Mouse  PACKAGE = Mouse::Object
 
 SV*
index d724f93..fbe8ab8 100644 (file)
@@ -221,7 +221,7 @@ mouse_accessor_get_mg(pTHX_ CV* const xsub){
 */
 
 CV*
-mouse_install_simple_accessor(pTHX_ const char* const fq_name, const char* const key, I32 const keylen, XSUBADDR_t const accessor_impl){
+mouse_install_simple_accessor(pTHX_ const char* const fq_name, const char* const key, I32 const keylen, XSUBADDR_t const accessor_impl, void* const dptr, I32 const dlen){
     CV* const xsub = newXS((char*)fq_name, accessor_impl, __FILE__);
     SV* const slot = newSVpvn_share(key, keylen, 0U);
     MAGIC* mg;
@@ -231,8 +231,11 @@ mouse_install_simple_accessor(pTHX_ const char* const fq_name, const char* const
         sv_2mortal((SV*)xsub);
     }
 
-    mg = sv_magicext((SV*)xsub, slot, PERL_MAGIC_ext, &mouse_accessor_vtbl, NULL, 0);
+    mg = sv_magicext((SV*)xsub, slot, PERL_MAGIC_ext, &mouse_accessor_vtbl, (char*)dptr, dlen);
     SvREFCNT_dec(slot); /* sv_magicext() increases refcnt in mg_obj */
+    if(dlen == HEf_SVKEY){
+        SvREFCNT_dec(dptr);
+    }
 
     /* NOTE:
      * although we use MAGIC for gc, we also store mg to CvXSUBANY for efficiency (gfx)
@@ -246,15 +249,25 @@ XS(XS_Mouse_simple_reader)
 {
     dVAR; dXSARGS;
     dMOUSE_self;
-    SV* const slot = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr);
+    MAGIC* const mg = (MAGIC*)XSANY.any_ptr;
     SV* value;
 
     if (items != 1) {
-        croak("Expected exactly one argument for a reader for '%"SVf"'", slot);
+        croak("Expected exactly one argument for a reader for '%"SVf"'", MOUSE_mg_slot(mg));
     }
 
-    value = get_slot(self, slot);
-    ST(0) = value ? value : &PL_sv_undef;
+    value = get_slot(self, MOUSE_mg_slot(mg));
+    if(!value) {
+        if(MOUSE_mg_ptr(mg)){
+            /* the default value must be a SV */
+            assert(MOUSE_mg_len(mg) == HEf_SVKEY);
+            value = (SV*)MOUSE_mg_ptr(mg);
+        }
+        else{
+            value = &PL_sv_undef;
+        }
+    }
+    ST(0) = value;
     XSRETURN(1);
 }
 
@@ -413,7 +426,7 @@ CODE:
     SV* const slot = mcall0s(attr, "name");
     STRLEN len;
     const char* const pv = SvPV_const(slot, len);
-    RETVAL = mouse_install_simple_accessor(aTHX_ NULL, pv, len, XS_Mouse_simple_clearer);
+    RETVAL = mouse_install_simple_accessor(aTHX_ NULL, pv, len, XS_Mouse_simple_clearer, NULL, 0);
 }
 OUTPUT:
     RETVAL
@@ -425,7 +438,7 @@ CODE:
     SV* const slot = mcall0s(attr, "name");
     STRLEN len;
     const char* const pv = SvPV_const(slot, len);
-    RETVAL = mouse_install_simple_accessor(aTHX_ NULL, pv, len, XS_Mouse_simple_predicate);
+    RETVAL = mouse_install_simple_accessor(aTHX_ NULL, pv, len, XS_Mouse_simple_predicate, NULL, 0);
 }
 OUTPUT:
     RETVAL
index a7bb4d4..30163fb 100644 (file)
@@ -218,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_SIMPLE_READER_WITH_DEFAULTS(Attribute, accessor_metaclass, "Mouse::Meta::Method::Accessor::XS");