Class::MOP::Attribute->meta->add_method('clone' => sub {
my $self = shift;
- $self->meta->clone_object($self, @_);
+ my $cloned = $self->meta->clone_object($self, @_);
+ $cloned->BUILD();
+ return $cloned;
});
## --------------------------------------------------------
confess("A required attribute must have either 'init_arg', 'builder', or 'default'");
}
- $class->_new(\%options);
+ my $self = $class->_new(\%options);
+ $self->BUILD(); # Initializer in XS
+ return $self;
}
sub _new {
my %options = @_;
(blessed($self))
|| confess "Can only clone an instance";
- return bless { %{$self}, %options } => ref($self);
+ my $cloned = bless { %{$self}, %options } => ref($self);
+ $cloned->BUILD();
+ return $cloned;
}
sub initialize_instance_slot {
const mop_instance_vtbl* mop_get_default_instance_vtbl(pTHX);
#define MOP_mg_obj(mg) ((mg)->mg_obj)
-#define MOP_mg_vtbl(mg) ((const mop_instance_vtbl*)(mg)->mg_ptr)
+#define MOP_mg_ptr(mg) ((mg)->mg_ptr)
+#define MOP_mg_vtbl(mg) ((const mop_instance_vtbl*)MOP_mg_ptr(mg))
#define MOP_mg_flags(mg) ((mg)->mg_private)
+#define MOP_mg_obj_refcounted_on(mg) (void)((mg)->mg_flags |= MGf_REFCOUNTED);
+
#define MOP_mg_slot(mg) MOP_mg_obj(mg)
#define MOP_mg_create_instance(mg, stash) MOP_mg_vtbl(mg)->create_instance (aTHX_ (stash))
#define MOP_mg_delete_slot(mg, o) MOP_mg_vtbl(mg)->delete_slot (aTHX_ (o), MOP_mg_slot(mg))
#define MOP_mg_weaken_slot(mg, o) MOP_mg_vtbl(mg)->weaken_slot (aTHX_ (o), MOP_mg_slot(mg))
+/* Class::MOP::Attribute stuff */
+
+MAGIC* mop_attr_get_mg(pTHX_ SV* const attr);
/* Class::MOP::Method::Accessor stuff */
#include "mop.h"
+static MGVTBL mop_attr_vtbl;
+
+
+MAGIC*
+mop_attr_get_mg(pTHX_ SV* const attr){
+ if(!SvROK(attr)) croak("Invalid object");
+
+ return mop_mg_find(aTHX_ SvRV(attr), &mop_attr_vtbl, MOPf_DIE_ON_FAIL);
+}
+
+
MODULE = Class::MOP::Attribute PACKAGE = Class::MOP::Attribute
PROTOTYPES: DISABLE
INSTALL_SIMPLE_PREDICATE(Attribute, initializer);
INSTALL_SIMPLE_PREDICATE(Attribute, default);
+void
+BUILD(SV* self)
+PREINIT:
+ mop_instance_vtbl* vtbl;
+CODE:
+ if(!( SvROK(self) && SvOBJECT(SvRV(self)) )){
+ croak("Invalid object");
+ }
+ sv_magicext(SvRV(self), NULL, PERL_MAGIC_ext, &mop_attr_vtbl, NULL, 0);
+
/* $key = $accessor->associated_attribute->name */
SV* const attr = mop_call0(aTHX_ accessor, mop_associated_attribute);
SV* const key = mop_call0(aTHX_ attr, mop_name);
+
STRLEN klen;
const char* const kpv = SvPV_const(key, klen);
- return mop_install_accessor(aTHX_ NULL /* anonymous */, kpv, klen, accessor_impl, vtbl);
+ MAGIC* mg = mop_attr_get_mg(aTHX_ attr);
+
+ CV* const xsub = newXS(NULL, accessor_impl, __FILE__);
+ sv_2mortal((SV*)xsub);
+
+ /* XXX: when attr is destroyed, all the associated xsub must be released */
+ CvXSUBANY(xsub).any_ptr = (void*)mg;
+
+ MOP_mg_obj(mg) = newSVpvn_share(kpv, klen, 0U);
+ MOP_mg_obj_refcounted_on(mg);
+
+ MOP_mg_ptr(mg) = vtbl; /* FIXME */
+
+ return xsub;
}
SV*