-
/* These two functions attach magic with no behavior to an SV.
*
* The stashed value is reference counted, and is destroyed when it's parent
CV *trigger;
CV *initializer;
- CV *writer; /* used by the initializer */
+ SV *writer; /* used by the initializer */
SV *meta_attr; /* the Moose::Meta::Attribute */
AV *cvs; /* an array of CVs which use this attr, see delete_mi */
+/* Moose::Meta::Instance level API */
+STATIC SV *get_slot_lvalue(pTHX_ SV *self, ATTR *attr);
+STATIC bool set_slot_value(pTHX_ SV *self, ATTR *attr, SV *value);
+STATIC bool has_slot_value(pTHX_ SV *self, ATTR *attr);
+STATIC SV *create_instance(pTHX_ MI *mi);
+STATIC SV *deinitialize_slot(pTHX_ SV *self, ATTR *attr);
+
+/* Moose::Meta::Attribute level API */
+STATIC void attr_set_initial_value(pTHX_ SV *self, ATTR *attr, SV *value);
+STATIC SV *attr_get_value(pTHX_ SV *self, ATTR *attr);
+STATIC void attr_set_value(pTHX_ SV *self, ATTR *attr, SV *value);
+STATIC SV *attr_clear_value(pTHX_ SV *self, ATTR *attr);
+STATIC bool attr_has_value(pTHX_ SV *self, ATTR *attr);
+STATIC SV *class_new_object(pTHX_ MI *mi, HV *params);
+
+
+/* Moose::Meta::Attribute level API (XSUBs) */
+STATIC CV *new_attr_method (pTHX_ SV *attr, XSPROTO(body), char *name);
+STATIC XS(initializer); /* only used by attr_set_initial_value */
+STATIC XS(reader);
+STATIC XS(writer);
+STATIC XS(accessor);
+STATIC XS(predicate);
+STATIC XS(clearer);
+STATIC XS(new_object);
+
+STATIC ATTR *define_attr(pTHX_ CV *cv);
+
+
+/* This macro is used in the XS subs to set up the 'attr' variable.
+ *
+ * if XSANY is NULL then define_attr is called on the CV, to set the pointer
+ * to the ATTR struct.
+ * */
+#define dATTR ATTR *attr = (XSANY.any_i32 ? INT2PTR(ATTR *, (XSANY.any_i32)) : define_attr(aTHX_ cv))
+
}
}
+
+STATIC XS(initializer)
+{
+#ifdef dVAR
+ dVAR;
+#endif
+ dXSARGS;
+ dATTR;
+
+ if (items != 2)
+ Perl_croak(aTHX_ "Usage: %s(%s, %s)", GvNAME(CvGV(cv)), "self", "value");
+
+ SP -= items;
+
+ attr_set_common(aTHX_ ST(0), attr, ST(1));
+
+ XSRETURN_EMPTY;
+}
+
STATIC void attr_set_initial_value(pTHX_ SV *self, ATTR *attr, SV *value) {
if ( attr->initializer ) {
- croak("todo");
+ if ( !attr->writer ) {
+ attr->writer = newRV_inc((SV *)new_attr_method(aTHX_ attr->meta_attr, initializer, NULL ));
+ }
+
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
+
+ XPUSHs(self);
+ XPUSHs(sv_2mortal(newSVsv(value)));
+ XPUSHs(attr->writer);
+ XPUSHs(attr->meta_attr);
+
+ PUTBACK;
+ call_sv((SV *)attr->initializer, G_VOID);
+
+ FREETMPS;
+ LEAVE;
} else {
attr_set_common(aTHX_ self, attr, value);
}
}
}
+STATIC bool attr_has_value(pTHX_ SV *self, ATTR *attr) {
+ return has_slot_value(aTHX_ self, attr);
+}
+STATIC SV *attr_clear_value(pTHX_ SV *self, ATTR *attr) {
+ return deinitialize_slot(aTHX_ self, attr);
+}
-/* This macro is used in the XS subs to set up the 'attr' variable.
- *
- * if XSANY is NULL then define_attr is called on the CV, to set the pointer
- * to the ATTR struct.
- * */
-#define dATTR ATTR *attr = (XSANY.any_i32 ? INT2PTR(ATTR *, (XSANY.any_i32)) : define_attr(aTHX_ cv))
-
-
-STATIC XS(reader);
STATIC XS(reader)
{
#ifdef dVAR
}
}
-STATIC XS(writer);
STATIC XS(writer)
{
#ifdef dVAR
XSRETURN(1);
}
-STATIC XS(accessor);
STATIC XS(accessor)
{
#ifdef dVAR
XSRETURN(1);
}
-STATIC XS(predicate);
STATIC XS(predicate)
{
#ifdef dVAR
SP -= items;
- if ( has_slot_value(aTHX_ ST(0), attr) )
+ if ( attr_has_value(aTHX_ ST(0), attr) )
XSRETURN_YES;
else
XSRETURN_NO;
}
+STATIC XS(clearer)
+{
+#ifdef dVAR
+ dVAR;
+#endif
+ dXSARGS;
+ dATTR;
+
+ if (items != 1)
+ Perl_croak(aTHX_ "Usage: %s(%s)", GvNAME(CvGV(cv)), "self");
+ SP -= items;
+
+ attr_clear_value(aTHX_ ST(0), attr);
+
+ XSRETURN_EMPTY;
+}
xs_body_writer,
xs_body_accessor,
xs_body_predicate,
+ xs_body_initializer,
+ xs_body_clearer,
max_xs_body
};
writer,
accessor,
predicate,
+ initializer,
+ clearer,
};
MODULE = Moose PACKAGE = Moose::XS
PREINIT:
char *pv = SvOK(name) ? SvPV_nolen(name) : NULL;
ALIAS:
- new_reader = xs_body_reader
- new_writer = xs_body_writer
- new_accessor = xs_body_accessor
- new_predicate = xs_body_predicate
+ new_reader = xs_body_reader
+ new_writer = xs_body_writer
+ new_accessor = xs_body_accessor
+ new_predicate = xs_body_predicate
+ new_initializer = xs_body_initializer
+ new_clearer = xs_body_clearer
CODE:
if ( ix >= max_xs_body )
croak("Unknown Moose::XS body type");