X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMouse.git;a=blobdiff_plain;f=xs-src%2FMouse.xs;h=8d0f3a815d7e27af035c6e13264f504087d84259;hp=c34ad16ec9209c9ef41d223619323c0a824c385f;hb=646c0371bdfda5817f842c54577c4d5605a4c3c0;hpb=d7d8d49b322c4d0f274aaafb049b324e1de6b552 diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index c34ad16..8d0f3a8 100644 --- a/xs-src/Mouse.xs +++ b/xs-src/Mouse.xs @@ -2,105 +2,98 @@ SV* mouse_package; SV* mouse_namespace; +SV* mouse_methods; +SV* mouse_name; -MODULE = Mouse PACKAGE = Mouse::Util +MODULE = Mouse PACKAGE = Mouse PROTOTYPES: DISABLE BOOT: mouse_package = newSVpvs_share("package"); mouse_namespace = newSVpvs_share("namespace"); + mouse_methods = newSVpvs_share("methods"); + mouse_name = newSVpvs_share("name"); + + MOUSE_CALL_BOOT(Mouse__Util); MOUSE_CALL_BOOT(Mouse__Util__TypeConstraints); + MOUSE_CALL_BOOT(Mouse__Meta__Method__Accessor__XS); -bool -is_class_loaded(SV* sv = &PL_sv_undef) +MODULE = Mouse PACKAGE = Mouse::Meta::Module -void -get_code_info(CV* code) -PREINIT: - GV* gv; - HV* stash; -PPCODE: - if((gv = CvGV(code)) && isGV(gv) && (stash = GvSTASH(gv))){ - EXTEND(SP, 2); - mPUSHs(newSVpvn_share(HvNAME_get(stash), HvNAMELEN_get(stash), 0U)); - mPUSHs(newSVpvn_share(GvNAME_get(gv), GvNAMELEN_get(gv), 0U)); - } +BOOT: + INSTALL_SIMPLE_READER_WITH_KEY(Module, name, package); + INSTALL_SIMPLE_READER_WITH_KEY(Module, _method_map, methods); + INSTALL_SIMPLE_READER_WITH_KEY(Module, _attribute_map, attributes); -SV* -get_code_package(CV* code) -PREINIT: - HV* stash; +HV* +namespace(SV* self) CODE: - if(CvGV(code) && isGV(CvGV(code)) && (stash = GvSTASH(CvGV(code)))){ - RETVAL = newSVpvn_share(HvNAME_get(stash), HvNAMELEN_get(stash), 0U); - } - else{ - RETVAL = &PL_sv_no; +{ + SV* const package = mouse_instance_get_slot(aTHX_ self, mouse_package); + if(!(package && SvOK(package))){ + croak("No package name defined"); } + RETVAL = gv_stashsv(package, GV_ADDMULTI); +} OUTPUT: RETVAL -CV* -get_code_ref(SV* package, SV* name) +# ignore extra arguments for extensibility +void +add_method(SV* self, SV* name, SV* code, ...) CODE: { - HV* stash; - HE* he; + SV* const package = mouse_instance_get_slot(aTHX_ self, mouse_package); /* $self->{package} */ + SV* const methods = mouse_instance_get_slot(aTHX_ self, mouse_methods); /* $self->{methods} */ + GV* gv; + SV* code_ref; - if(!SvOK(package)){ - croak("You must define a package name"); + if(!(package && SvOK(package))){ + croak("No package name defined"); } + + SvGETMAGIC(name); + SvGETMAGIC(code); + if(!SvOK(name)){ - croak("You must define a subroutine name"); + mouse_throw_error(self, NULL, "You must define a method name"); } - - stash = gv_stashsv(package, FALSE); - if(!stash){ - XSRETURN_UNDEF; + if(!SvROK(code)){ + mouse_throw_error(self, NULL, "You must define a CODE reference"); } - he = hv_fetch_ent(stash, name, FALSE, 0U); - if(he){ - GV* const gv = (GV*)hv_iterval(stash, he); - if(!isGV(gv)){ /* special constant or stub */ - STRLEN len; - const char* const pv = SvPV_const(name, len); - gv_init(gv, stash, pv, len, GV_ADDMULTI); + + 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} */ + if(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV){ + mouse_throw_error(self, NULL, "Not a CODE reference"); } - RETVAL = GvCVu(gv); - } - else{ - RETVAL = NULL; + code_ref = sv; } - if(!RETVAL){ - XSRETURN_UNDEF; + /* *{$package . '::' . $name} -> *gv */ + gv = gv_fetchpv(form("%"SVf"::%"SVf, package, name), GV_ADDMULTI, SVt_PVCV); + if(GvCVu(gv)){ /* delete *slot{gv} to work around "redefine" warning */ + SvREFCNT_dec(GvCV(gv)); + GvCV(gv) = NULL; } -} -OUTPUT: - RETVAL + sv_setsv_mg((SV*)gv, code_ref); /* *gv = $code_ref */ + mouse_instance_set_slot(aTHX_ methods, name, code); /* $self->{methods}{$name} = $code */ -MODULE = Mouse PACKAGE = Mouse::Meta::Module + /* TODO: name the CODE ref if it's anonymous */ + //code_entity = (CV*)SvRV(code_ref); + //if(CvANON(code_entity) + // && CvGV(code_entity) /* a cv under construction has no gv */ ){ -BOOT: - INSTALL_SIMPLE_READER_WITH_KEY(Module, name, package); - INSTALL_SIMPLE_READER_WITH_KEY(Module, _method_map, methods); - INSTALL_SIMPLE_READER_WITH_KEY(Module, _attribute_map, attributes); - -HV* -namespace(SV* self) -CODE: -{ - SV* const package = mouse_instance_get_slot(aTHX_ self, mouse_package); - if(!(package && SvOK(package))){ - croak("No package name"); - } - RETVAL = gv_stashsv(package, GV_ADDMULTI); + // CvGV(code_entity) = gv; + // CvANON_off(code_entity); + //} } -OUTPUT: - RETVAL MODULE = Mouse PACKAGE = Mouse::Meta::Class @@ -190,56 +183,3 @@ BOOT: INSTALL_SIMPLE_PREDICATE_WITH_KEY(TypeConstraint, has_coercion, _compiled_type_coercion); -MODULE = Mouse PACKAGE = Mouse::Meta::Method::Accessor::XS - -CV* -_generate_accessor(klass, SV* attr, metaclass) -CODE: -{ - RETVAL = mouse_instantiate_xs_accessor(aTHX_ attr, mouse_xs_accessor); -} -OUTPUT: - RETVAL - -CV* -_generate_reader(klass, SV* attr, metaclass) -CODE: -{ - RETVAL = mouse_instantiate_xs_accessor(aTHX_ attr, mouse_xs_reader); -} -OUTPUT: - RETVAL - -CV* -_generate_writer(klass, SV* attr, metaclass) -CODE: -{ - RETVAL = mouse_instantiate_xs_accessor(aTHX_ attr, mouse_xs_writer); -} -OUTPUT: - RETVAL - -CV* -_generate_clearer(klass, SV* attr, metaclass) -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, mouse_xs_simple_clearer); -} -OUTPUT: - RETVAL - -CV* -_generate_predicate(klass, SV* attr, metaclass) -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, mouse_xs_simple_predicate); -} -OUTPUT: - RETVAL -