Merge commit 'origin/topic/xs-attr-template' into topic/unified-method-generation...
gfx [Sat, 15 Aug 2009 12:30:52 +0000 (21:30 +0900)]
Conflicts:
lib/Class/MOP/Class.pm
xs/Class.xs

14 files changed:
1  2 
lib/Class/MOP/Attribute.pm
lib/Class/MOP/Class.pm
lib/Class/MOP/Instance.pm
lib/Class/MOP/Method.pm
lib/Class/MOP/Method/Accessor.pm
lib/Class/MOP/Method/Constructor.pm
lib/Class/MOP/Method/Generated.pm
lib/Class/MOP/Method/Inlined.pm
mop.c
mop.h
xs/Class.xs
xs/MOP.xs
xs/MethodAccessor.xs
xs/Package.xs

Simple merge
@@@ -341,13 -337,15 +341,13 @@@ sub create 
  # all these attribute readers will be bootstrapped
  # away in the Class::MOP bootstrap section
  
- sub get_attribute_map        { $_[0]->{'attributes'}                  }
- sub attribute_metaclass      { $_[0]->{'attribute_metaclass'}         }
- sub instance_metaclass       { $_[0]->{'instance_metaclass'}          }
- sub immutable_trait          { $_[0]->{'immutable_trait'}             }
- sub constructor_class        { $_[0]->{'constructor_class'}           }
- sub constructor_name         { $_[0]->{'constructor_name'}            }
- sub destructor_class         { $_[0]->{'destructor_class'}            }
+ #sub get_attribute_map        { $_[0]->{'attributes'}                  }
+ #sub attribute_metaclass      { $_[0]->{'attribute_metaclass'}         }
 -#sub method_metaclass         { $_[0]->{'method_metaclass'}            }
 -#sub wrapped_method_metaclass { $_[0]->{'wrapped_method_metaclass'}    }
+ #sub instance_metaclass       { $_[0]->{'instance_metaclass'}          }
+ #sub immutable_trait          { $_[0]->{'immutable_trait'}             }
+ #sub constructor_class        { $_[0]->{'constructor_class'}           }
+ #sub constructor_name         { $_[0]->{'constructor_name'}            }
+ #sub destructor_class         { $_[0]->{'destructor_class'}            }
  
  # Instance Construction & Cloning
  
Simple merge
Simple merge
@@@ -70,9 -52,21 +70,19 @@@ sub _new 
  
  ## accessors
  
- sub associated_attribute { (shift)->{'attribute'}     }
- sub accessor_type        { (shift)->{'accessor_type'} }
+ #sub associated_attribute { (shift)->{'attribute'}     }
+ #sub accessor_type        { (shift)->{'accessor_type'} }
 -sub can_xs {
++sub _can_xs {
+     my($self, $method_name) = @_;
+     # don't use $method_name here, but there may be cases it is required.
+     # FIXME: I didn't know how to detect it properly (gfx)
+     return ref($self) eq __PACKAGE__
 -           && $self->associated_attribute->associated_class->instance_metaclass eq 'Class::MOP::Instance';
++           && $self->associated_metaclass->instance_metaclass eq 'Class::MOP::Instance';
+ }
  
 -sub attribute_name{ (shift)->associated_attribute->name }
 -
  ## factory
  
  sub initialize_body {
@@@ -87,10 -81,13 +97,13 @@@ sub _initialize_body 
      my $method_name = join "_" => (
          '_generate',
          $self->accessor_type,
-         'method',
-         ($self->is_inline ? 'inline' : ())
+         'method'
      );
  
+     if($self->is_inline){
 -        $method_name .= $self->can_xs($method_name) ? '_xs' : '_inline';
++        $method_name .= $self->_can_xs($method_name) ? '_xs' : '_inline';
+     }
      $self->{'body'} = $self->$method_name();
  }
  
Simple merge
Simple merge
Simple merge
diff --cc mop.c
Simple merge
diff --cc mop.h
--- 1/mop.h
--- 2/mop.h
+++ b/mop.h
@@@ -48,7 -42,15 +42,16 @@@ XS(mop_xs_simple_clearer)
  
  extern SV *mop_method_metaclass;
  extern SV *mop_associated_metaclass;
++extern SV *mop_associated_attribute;
  extern SV *mop_wrap;
+ extern SV *mop_methods;
+ extern SV *mop_name;
+ extern SV *mop_body;
+ extern SV *mop_package;
+ extern SV *mop_package_name;
+ extern SV *mop_package_cache_flag;
+ extern SV *mop_VERSION;
+ extern SV *mop_ISA;
  
  UV mop_check_package_cache_flag(pTHX_ HV *stash);
  int mop_get_code_info (SV *coderef, char **pkg, char **name);
diff --cc xs/Class.xs
index 0000000,d779683..cca3823
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,129 +1,15 @@@
+ #include "mop.h"
 -static void
 -mop_update_method_map(pTHX_ SV *const self, SV *const class_name, HV *const stash, HV *const map)
 -{
 -    const char *const class_name_pv = HvNAME(stash); /* must be HvNAME(stash), not SvPV_nolen_const(class_name) */
 -    SV   *method_metaclass_name;
 -    char *method_name;
 -    I32   method_name_len;
 -    SV   *coderef;
 -    HV   *symbols;
 -    dSP;
 -
 -    symbols = mop_get_all_package_symbols(stash, TYPE_FILTER_CODE);
 -    sv_2mortal((SV*)symbols);
 -    (void)hv_iterinit(symbols);
 -    while ( (coderef = hv_iternextsv(symbols, &method_name, &method_name_len)) ) {
 -        CV *cv = (CV *)SvRV(coderef);
 -        char *cvpkg_name;
 -        char *cv_name;
 -        SV *method_slot;
 -        SV *method_object;
 -
 -        if (!mop_get_code_info(coderef, &cvpkg_name, &cv_name)) {
 -            continue;
 -        }
 -
 -        /* this checks to see that the subroutine is actually from our package  */
 -        if ( !(strEQ(cvpkg_name, "constant") && strEQ(cv_name, "__ANON__")) ) {
 -            if ( strNE(cvpkg_name, class_name_pv) ) {
 -                continue;
 -            }
 -        }
 -
 -        method_slot = *hv_fetch(map, method_name, method_name_len, TRUE);
 -        if ( SvOK(method_slot) ) {
 -            SV *const body = mop_call0(aTHX_ method_slot, mop_body); /* $method_object->body() */
 -            if ( SvROK(body) && ((CV *) SvRV(body)) == cv ) {
 -                continue;
 -            }
 -        }
 -
 -        method_metaclass_name = mop_call0(aTHX_ self, mop_method_metaclass); /* $self->method_metaclass() */
 -
 -        /*
 -            $method_object = $method_metaclass->wrap(
 -                $cv,
 -                associated_metaclass => $self,
 -                package_name         => $class_name,
 -                name                 => $method_name
 -            );
 -        */
 -        ENTER;
 -        SAVETMPS;
 -
 -        PUSHMARK(SP);
 -        EXTEND(SP, 8);
 -        PUSHs(method_metaclass_name); /* invocant */
 -        mPUSHs(newRV_inc((SV *)cv));
 -        PUSHs(mop_associated_metaclass);
 -        PUSHs(self);
 -        PUSHs(mop_package_name);
 -        PUSHs(class_name);
 -        PUSHs(mop_name);
 -        mPUSHs(newSVpv(method_name, method_name_len));
 -        PUTBACK;
 -
 -        call_sv(mop_wrap, G_SCALAR | G_METHOD);
 -        SPAGAIN;
 -        method_object = POPs;
 -        PUTBACK;
 -        /* $map->{$method_name} = $method_object */
 -        sv_setsv(method_slot, method_object);
 -
 -        FREETMPS;
 -        LEAVE;
 -    }
 -}
+ MODULE = Class::MOP::Class    PACKAGE = Class::MOP::Class
++PROTOTYPES: DISABLE
++
+ BOOT:
+     INSTALL_SIMPLE_READER_WITH_KEY(Class, get_attribute_map, attributes);
 -    /* INSTALL_SIMPLE_READER_WITH_KEY(Class, _method_map, methods); */
+     INSTALL_SIMPLE_READER(Class, attribute_metaclass);
 -    INSTALL_SIMPLE_READER(Class, method_metaclass);
 -    INSTALL_SIMPLE_READER(Class, wrapped_method_metaclass);
+     INSTALL_SIMPLE_READER(Class, instance_metaclass);
+     INSTALL_SIMPLE_READER(Class, immutable_trait);
+     INSTALL_SIMPLE_READER(Class, constructor_name);
+     INSTALL_SIMPLE_READER(Class, constructor_class);
+     INSTALL_SIMPLE_READER(Class, destructor_class);
 -
 -
 -PROTOTYPES: DISABLE
 -
 -void
 -get_method_map(self)
 -    SV *self
 -    PREINIT:
 -        HV *const obj        = (HV *)SvRV(self);
 -        SV *const class_name = HeVAL( hv_fetch_ent(obj, mop_package, 0, 0U) );
 -        HV *const stash      = gv_stashsv(class_name, 0);
 -        UV current;
 -        SV *cache_flag;
 -        SV *map_ref;
 -    PPCODE:
 -        if (!stash) {
 -             mXPUSHs(newRV_noinc((SV *)newHV()));
 -             return;
 -        }
 -
 -        current    = mop_check_package_cache_flag(aTHX_ stash);
 -        cache_flag = HeVAL( hv_fetch_ent(obj, mop_package_cache_flag, TRUE, 0U));
 -        map_ref    = HeVAL( hv_fetch_ent(obj, mop_methods, TRUE, 0U));
 -
 -        /* $self->{methods} does not yet exist (or got deleted) */
 -        if ( !SvROK(map_ref) || SvTYPE(SvRV(map_ref)) != SVt_PVHV ) {
 -            SV *new_map_ref = newRV_noinc((SV *)newHV());
 -            sv_2mortal(new_map_ref);
 -            sv_setsv(map_ref, new_map_ref);
 -        }
 -
 -        if ( !SvOK(cache_flag) || SvUV(cache_flag) != current ) {
 -            mop_update_method_map(aTHX_ self, class_name, stash, (HV *)SvRV(map_ref));
 -            sv_setuv(cache_flag, mop_check_package_cache_flag(aTHX_ stash)); /* update_cache_flag() */
 -        }
 -
 -        XPUSHs(map_ref);
diff --cc xs/MOP.xs
+++ b/xs/MOP.xs
@@@ -2,7 -2,16 +2,17 @@@
  
  SV *mop_method_metaclass;
  SV *mop_associated_metaclass;
++SV *mop_associated_attribute;
  SV *mop_wrap;
+ SV *mop_methods;
+ SV *mop_name;
+ SV *mop_body;
+ SV *mop_package;
+ SV *mop_package_name;
+ SV *mop_package_cache_flag;
+ SV *mop_VERSION;
+ SV *mop_ISA;
  
  static bool
  find_method (const char *key, STRLEN keylen, SV *val, void *ud)
@@@ -24,15 -36,24 +37,25 @@@ MODULE = Class::MOP   PACKAGE = Class::
  PROTOTYPES: DISABLE
  
  BOOT:
-     mop_prehash_keys();
-     mop_method_metaclass     = newSVpvs("method_metaclass");
-     mop_wrap                 = newSVpvs("wrap");
-     mop_associated_metaclass = newSVpvs("associated_metaclass");
+     mop_method_metaclass     = MAKE_KEYSV(method_metaclass);
+     mop_wrap                 = MAKE_KEYSV(wrap);
+     mop_associated_metaclass = MAKE_KEYSV(associated_metaclass);
++    mop_associated_attribute = MAKE_KEYSV(associated_attribute);
+     mop_methods              = MAKE_KEYSV(methods);
+     mop_name                 = MAKE_KEYSV(name);
+     mop_body                 = MAKE_KEYSV(body);
+     mop_package              = MAKE_KEYSV(package);
+     mop_package_name         = MAKE_KEYSV(package_name);
+     mop_package_cache_flag   = MAKE_KEYSV(_package_cache_flag);
+     mop_VERSION              = MAKE_KEYSV(VERSION);
+     mop_ISA                  = MAKE_KEYSV(ISA);
  
      MOP_CALL_BOOT (boot_Class__MOP__Package);
+     MOP_CALL_BOOT (boot_Class__MOP__Class);
      MOP_CALL_BOOT (boot_Class__MOP__Attribute);
      MOP_CALL_BOOT (boot_Class__MOP__Method);
+     MOP_CALL_BOOT (boot_Class__MOP__Instance);
+     MOP_CALL_BOOT (boot_Class__MOP__Method__Accessor);
  
  # use prototype here to be compatible with get_code_info from Sub::Identify
  void
index 0000000,86dad34..037ed41
mode 000000,100755..100755
--- /dev/null
@@@ -1,0 -1,54 +1,56 @@@
+ #include "mop.h"
+ static CV*
 -mop_instantiate_xs_accessor(pTHX_ SV* const meta_attr, XSPROTO(accessor_impl)){
 -    SV* const key = mop_call0(aTHX_ meta_attr, sv_2mortal(newSVpvs("attribute_name")));
++mop_instantiate_xs_accessor(pTHX_ SV* const accessor, XSPROTO(accessor_impl)){
++    /* $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 len;
+     const char* const pv = SvPV_const(key, len);
+     return mop_install_simple_accessor(aTHX_ NULL /* anonymous */, pv, len, accessor_impl);
+ }
+ MODULE = Class::MOP::Method::Accessor   PACKAGE = Class::MOP::Method::Accessor
+ PROTOTYPES: DISABLE
+ BOOT:
+     INSTALL_SIMPLE_READER_WITH_KEY(Method::Accessor, associated_attribute, attribute);
+     INSTALL_SIMPLE_READER(Method::Accessor, accessor_type);
+ CV*
+ _generate_accessor_method_xs(SV* self)
+ CODE:
+     RETVAL = mop_instantiate_xs_accessor(aTHX_ self, mop_xs_simple_accessor);
+ OUTPUT:
+     RETVAL
+ CV*
+ _generate_reader_method_xs(SV* self)
+ CODE:
+     RETVAL = mop_instantiate_xs_accessor(aTHX_ self, mop_xs_simple_reader);
+ OUTPUT:
+     RETVAL
+ CV*
+ _generate_writer_method_xs(SV* self)
+ CODE:
+     RETVAL = mop_instantiate_xs_accessor(aTHX_ self, mop_xs_simple_writer);
+ OUTPUT:
+     RETVAL
+ CV*
+ _generate_predicate_method_xs(SV* self)
+ CODE:
+     RETVAL = mop_instantiate_xs_accessor(aTHX_ self, mop_xs_simple_predicate);
+ OUTPUT:
+     RETVAL
+ CV*
+ _generate_clearer_method_xs(SV* self)
+ CODE:
+     RETVAL = mop_instantiate_xs_accessor(aTHX_ self, mop_xs_simple_clearer);
+ OUTPUT:
+     RETVAL
diff --cc xs/Package.xs
@@@ -1,82 -1,5 +1,82 @@@
  #include "mop.h"
  
 +static void
 +mop_update_method_map(pTHX_ SV *const self, SV *const class_name, HV *const stash, HV *const map)
 +{
 +    const char *const class_name_pv = HvNAME(stash); /* must be HvNAME(stash), not SvPV_nolen_const(class_name) */
 +    SV   *method_metaclass_name;
 +    char *method_name;
 +    I32   method_name_len;
 +    SV   *coderef;
 +    HV   *symbols;
 +    dSP;
 +
 +    symbols = mop_get_all_package_symbols(stash, TYPE_FILTER_CODE);
 +    sv_2mortal((SV*)symbols);
 +    (void)hv_iterinit(symbols);
 +    while ( (coderef = hv_iternextsv(symbols, &method_name, &method_name_len)) ) {
 +        CV *cv = (CV *)SvRV(coderef);
 +        char *cvpkg_name;
 +        char *cv_name;
 +        SV *method_slot;
 +        SV *method_object;
 +
 +        if (!mop_get_code_info(coderef, &cvpkg_name, &cv_name)) {
 +            continue;
 +        }
 +
 +        /* this checks to see that the subroutine is actually from our package  */
 +        if ( !(strEQ(cvpkg_name, "constant") && strEQ(cv_name, "__ANON__")) ) {
 +            if ( strNE(cvpkg_name, class_name_pv) ) {
 +                continue;
 +            }
 +        }
 +
 +        method_slot = *hv_fetch(map, method_name, method_name_len, TRUE);
 +        if ( SvOK(method_slot) ) {
-             SV *const body = mop_call0(aTHX_ method_slot, KEY_FOR(body)); /* $method_object->body() */
++            SV *const body = mop_call0(aTHX_ method_slot, mop_body); /* $method_object->body() */
 +            if ( SvROK(body) && ((CV *) SvRV(body)) == cv ) {
 +                continue;
 +            }
 +        }
 +
 +        method_metaclass_name = mop_call0(aTHX_ self, mop_method_metaclass); /* $self->method_metaclass() */
 +
 +        /*
 +            $method_object = $method_metaclass->wrap(
 +                $cv,
 +                associated_metaclass => $self,
 +                package_name         => $class_name,
 +                name                 => $method_name
 +            );
 +        */
 +        ENTER;
 +        SAVETMPS;
 +
 +        PUSHMARK(SP);
 +        EXTEND(SP, 8);
 +        PUSHs(method_metaclass_name); /* invocant */
 +        mPUSHs(newRV_inc((SV *)cv));
 +        PUSHs(mop_associated_metaclass);
 +        PUSHs(self);
-         PUSHs(KEY_FOR(package_name));
++        PUSHs(mop_package_name);
 +        PUSHs(class_name);
-         PUSHs(KEY_FOR(name));
++        PUSHs(mop_name);
 +        mPUSHs(newSVpv(method_name, method_name_len));
 +        PUTBACK;
 +
 +        call_sv(mop_wrap, G_SCALAR | G_METHOD);
 +        SPAGAIN;
 +        method_object = POPs;
 +        PUTBACK;
 +        /* $map->{$method_name} = $method_object */
 +        sv_setsv(method_slot, method_object);
 +
 +        FREETMPS;
 +        LEAVE;
 +    }
 +}
 +
  MODULE = Class::MOP::Package   PACKAGE = Class::MOP::Package
  
  PROTOTYPES: DISABLE
@@@ -112,39 -35,5 +112,42 @@@ get_all_package_symbols(self, filter=TY
          symbols = mop_get_all_package_symbols(stash, filter);
          PUSHs(sv_2mortal(newRV_noinc((SV *)symbols)));
  
 +void
 +get_method_map(self)
 +    SV *self
 +    PREINIT:
 +        HV *const obj        = (HV *)SvRV(self);
-         SV *const class_name = HeVAL( hv_fetch_ent(obj, KEY_FOR(package), 0, HASH_FOR(package)) );
++        SV *const class_name = HeVAL( hv_fetch_ent(obj, mop_package, 0, 0U) );
 +        HV *const stash      = gv_stashsv(class_name, 0);
 +        UV current;
 +        SV *cache_flag;
 +        SV *map_ref;
 +    PPCODE:
 +        if (!stash) {
 +             mXPUSHs(newRV_noinc((SV *)newHV()));
 +             return;
 +        }
 +
 +        current    = mop_check_package_cache_flag(aTHX_ stash);
-         cache_flag = HeVAL( hv_fetch_ent(obj, KEY_FOR(package_cache_flag), TRUE, HASH_FOR(package_cache_flag)));
-         map_ref    = HeVAL( hv_fetch_ent(obj, KEY_FOR(methods), TRUE, HASH_FOR(methods)));
++        cache_flag = HeVAL( hv_fetch_ent(obj, mop_package_cache_flag, TRUE, 0U));
++        map_ref    = HeVAL( hv_fetch_ent(obj, mop_methods, TRUE, 0U));
 +
 +        /* $self->{methods} does not yet exist (or got deleted) */
 +        if ( !SvROK(map_ref) || SvTYPE(SvRV(map_ref)) != SVt_PVHV ) {
 +            SV *new_map_ref = newRV_noinc((SV *)newHV());
 +            sv_2mortal(new_map_ref);
 +            sv_setsv(map_ref, new_map_ref);
 +        }
 +
 +        if ( !SvOK(cache_flag) || SvUV(cache_flag) != current ) {
 +            mop_update_method_map(aTHX_ self, class_name, stash, (HV *)SvRV(map_ref));
 +            sv_setuv(cache_flag, mop_check_package_cache_flag(aTHX_ stash)); /* update_cache_flag() */
 +        }
 +
 +        XPUSHs(map_ref);
 +
  BOOT:
      INSTALL_SIMPLE_READER_WITH_KEY(Package, name, package);
++    INSTALL_SIMPLE_READER_WITH_KEY(Package, _method_map, methods);
++    INSTALL_SIMPLE_READER(Package, method_metaclass);
++    INSTALL_SIMPLE_READER(Package, wrapped_method_metaclass);