mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const args, bool const is_cloning) {
AV* const xc = mouse_get_xc(aTHX_ meta);
AV* const attrs = MOUSE_xc_attrall(xc);
- I32 len = AvFILLp(attrs) + 1;
+ I32 const len = AvFILLp(attrs) + 1;
I32 i;
AV* triggers_queue = NULL;
I32 used = 0;
}
used++;
}
- else if(!is_cloning){ /* no init arg, noop while cloning */
+ else { /* no init arg */
if(flags & (MOUSEf_ATTR_HAS_DEFAULT | MOUSEf_ATTR_HAS_BUILDER)){
- if(!(flags & MOUSEf_ATTR_IS_LAZY)){
+ /* skip if the object has the slot (it occurs on cloning/reblessing) */
+ if(!(flags & MOUSEf_ATTR_IS_LAZY) && !has_slot(object, slot)){
mouse_xa_set_default(aTHX_ xa, object);
}
}
- else if(flags & MOUSEf_ATTR_IS_REQUIRED) {
+ /* don't check while cloning (or reblesseing) */
+ else if(!is_cloning && flags & MOUSEf_ATTR_IS_REQUIRED) {
mouse_throw_error(attr, NULL, "Attribute (%"SVf") is required", slot);
}
}
}
if(triggers_queue){
- len = AvFILLp(triggers_queue) + 1;
+ I32 const len = AvFILLp(triggers_queue) + 1;
for(i = 0; i < len; i++){
AV* const pair = (AV*)AvARRAY(triggers_queue)[i];
SV* const trigger = AvARRAY(pair)[0];
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_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");
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:
}
}
-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);
+ 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);
+}
+
+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,
+ "You must pass an instance of the metaclass (%"SVf"), not (%"SVf")",
+ mcall0(meta, mouse_name), object);
+ }
+
+ 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)
MODULE = Mouse PACKAGE = Mouse::Object
-SV*
+void
new(SV* klass, ...)
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){
}
/* 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);
+ 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)