Mouse
view release on metacpan or search on metacpan
xs-src/Mouse.xs view on Meta::CPAN
{
SV* const package = get_slot(self, mouse_package); /* $self->{package} */
SV* const methods = get_slot(self, mouse_methods); /* $self->{methods} */
GV* gv;
SV* code_ref;
if(!(package && SvOK(package))){
croak("No package name defined");
}
must_defined(name, "a method name");
must_ref (code, "a CODE reference", SVt_NULL); /* any reftype is OK */
code_ref = code;
if(SvTYPE(SvRV(code_ref)) != SVt_PVCV){
SV* sv = code_ref; /* used in tryAMAGICunDEREF */
SV** sp = &sv; /* used in tryAMAGICunDEREF */
tryAMAGICunDEREF(to_cv); /* try \&{$code} */
must_ref(code, "a CODE reference", SVt_PVCV);
code_ref = sv;
}
/* *{$package . '::' . $name} -> *gv */
gv = gv_fetchpv(form("%"SVf"::%"SVf, package, name), GV_ADDMULTI, SVt_PVCV);
mouse_install_sub(aTHX_ gv, code_ref);
/* CvMETHOD_on((CV*)SvRV(code_ref)); */
(void)set_slot(methods, name, code); /* $self->{methods}{$name} = $code */
}
MODULE = Mouse PACKAGE = Mouse::Meta::Class
BOOT:
{
CV* xsub;
INSTALL_SIMPLE_READER(Class, roles);
INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id);
INSTALL_SIMPLE_READER(Class, is_immutable);
INSTALL_INHERITABLE_CLASS_ACCESSOR(strict_constructor);
INSTALL_CLASS_HOLDER(Class, method_metaclass, "Mouse::Meta::Method");
INSTALL_CLASS_HOLDER(Class, attribute_metaclass, "Mouse::Meta::Attribute");
INSTALL_CLASS_HOLDER(Class, constructor_class, "Mouse::Meta::Method::Constructor::XS");
INSTALL_CLASS_HOLDER(Class, destructor_class, "Mouse::Meta::Method::Destructor::XS");
xsub = newXS("Mouse::Meta::Method::Constructor::XS::_generate_constructor",
XS_Mouse_value_holder, file);
CvXSUBANY(xsub).any_ptr
= newRV_inc((SV*)get_cvs("Mouse::Object::new", GV_ADD));
xsub = newXS("Mouse::Meta::Method::Destructor::XS::_generate_destructor",
XS_Mouse_value_holder, file);
CvXSUBANY(xsub).any_ptr
= newRV_inc((SV*)get_cvs("Mouse::Object::DESTROY", GV_ADD));
}
void
linearized_isa(SV* self)
PPCODE:
{
/* MOUSE_xc_stash() is not available because the xc system depends on
linearized_isa() */
HV* const stash = mouse_get_namespace(aTHX_ self);
AV* const linearized_isa = mro_get_linear_isa(stash);
I32 const len = AvFILLp(linearized_isa) + 1;
I32 i;
EXTEND(SP, len);
for(i = 0; i < len; i++){
PUSHs(AvARRAY(linearized_isa)[i]);
}
}
void
get_all_attributes(SV* self)
PPCODE:
{
AV* const xc = mouse_get_xc(aTHX_ self);
AV* const all_attrs = MOUSE_xc_attrall(xc);
I32 const len = AvFILLp(all_attrs) + 1;
I32 i;
EXTEND(SP, len);
for(i = 0; i < len; i++){
PUSHs( MOUSE_av_at(all_attrs, i) );
}
}
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;
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)));
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);
}
void
_initialize_object(SV* meta, SV* object, HV* args, bool is_cloning = FALSE)
CODE:
{
mouse_class_initialize_object(aTHX_ meta, object, args, is_cloning);
}
void
_invalidate_metaclass_cache(SV* meta)
CODE:
{
AV* const xc = mouse_get_xc_if_fresh(aTHX_ meta);
if(xc) {
SV* const gen = MOUSE_xc_gen(xc);
sv_setuv(gen, 0U);
}
delete_slot(meta, newSVpvs_flags("_mouse_cache_", SVs_TEMP));
}
MODULE = Mouse PACKAGE = Mouse::Meta::Role
BOOT:
INSTALL_SIMPLE_READER_WITH_KEY(Role, get_roles, roles);
INSTALL_SIMPLE_PREDICATE_WITH_KEY(Role, is_anon_role, anon_serial_id);
INSTALL_CLASS_HOLDER(Role, method_metaclass, "Mouse::Meta::Role::Method");
void
add_before_modifier(SV* self, SV* name, SV* modifier)
CODE:
{
av_push(mouse_get_modifier_storage(aTHX_ self, (enum mouse_modifier_t)ix, name), newSVsv(modifier));
}
ALIAS:
add_before_method_modifier = MOUSE_M_BEFORE
add_around_method_modifier = MOUSE_M_AROUND
add_after_method_modifier = MOUSE_M_AFTER
void
get_before_modifiers(SV* self, SV* name)
ALIAS:
get_before_method_modifiers = MOUSE_M_BEFORE
get_around_method_modifiers = MOUSE_M_AROUND
get_after_method_modifiers = MOUSE_M_AFTER
PPCODE:
{
AV* const storage = mouse_get_modifier_storage(aTHX_ self,
(enum mouse_modifier_t)ix, name);
I32 const len = av_len(storage) + 1;
if(GIMME_V == G_ARRAY) {
I32 i;
EXTEND(SP, len);
for(i = 0; i < len; i++){
PUSHs(*av_fetch(storage, i, TRUE));
}
}
else{
mPUSHi(len);
}
}
void
add_metaclass_accessor(SV* self, SV* name)
CODE:
{
SV* const klass = mcall0(self, mouse_name);
const char* fq_name = form("%"SVf"::%"SVf, klass, name);
STRLEN keylen;
const char* const key = SvPV_const(name, keylen);
mouse_simple_accessor_generate(aTHX_ fq_name, key, keylen,
XS_Mouse_inheritable_class_accessor, NULL, 0);
}
MODULE = Mouse PACKAGE = Mouse::Object
void
new(SV* klass, ...)
CODE:
{
SV* const meta = mouse_initialize_metaclass(aTHX_ klass);
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){
I32 i;
SPAGAIN;
PUSHMARK(SP);
EXTEND(SP, items);
for(i = 0; i < items; i++){
PUSHs(ST(i));
}
PUTBACK;
call_method_safes("BUILDARGS", G_SCALAR);
SPAGAIN;
args = POPs;
PUTBACK;
if(!IsHashRef(args)){
croak("BUILDARGS did not return a HASH reference");
( run in 0.876 second using v1.01-cache-2.11-cpan-5511b514fd6 )