Merge branch 'stable'
[gitmo/Class-MOP.git] / xs / MOP.xs
index 378f874..5644cd8 100644 (file)
--- a/xs/MOP.xs
+++ b/xs/MOP.xs
@@ -1,9 +1,5 @@
 #include "mop.h"
 
-SV *mop_method_metaclass;
-SV *mop_associated_metaclass;
-SV *mop_wrap;
-
 static bool
 find_method (const char *key, STRLEN keylen, SV *val, void *ud)
 {
@@ -15,10 +11,45 @@ find_method (const char *key, STRLEN keylen, SV *val, void *ud)
     return FALSE;
 }
 
+static bool
+check_version (SV *klass, SV *required_version)
+{
+    bool ret = 0;
+
+    dSP;
+    ENTER;
+    SAVETMPS;
+    PUSHMARK(SP);
+    EXTEND(SP, 2);
+    PUSHs(klass);
+    PUSHs(required_version);
+    PUTBACK;
+
+    call_method("VERSION", G_DISCARD|G_VOID|G_EVAL);
+
+    SPAGAIN;
+
+    if (!SvTRUE(ERRSV)) {
+        ret = 1;
+    }
+
+    PUTBACK;
+    FREETMPS;
+    LEAVE;
+
+    return ret;
+}
+
+EXTERN_C XS(boot_Class__MOP__Mixin__HasAttributes);
+EXTERN_C XS(boot_Class__MOP__Mixin__HasMethods);
 EXTERN_C XS(boot_Class__MOP__Package);
+EXTERN_C XS(boot_Class__MOP__Mixin__AttributeCore);
+EXTERN_C XS(boot_Class__MOP__Method);
+EXTERN_C XS(boot_Class__MOP__Method__Inlined);
+EXTERN_C XS(boot_Class__MOP__Method__Generated);
 EXTERN_C XS(boot_Class__MOP__Class);
 EXTERN_C XS(boot_Class__MOP__Attribute);
-EXTERN_C XS(boot_Class__MOP__Method);
+EXTERN_C XS(boot_Class__MOP__Instance);
 
 MODULE = Class::MOP   PACKAGE = Class::MOP
 
@@ -27,14 +58,16 @@ PROTOTYPES: DISABLE
 BOOT:
     mop_prehash_keys();
 
-    mop_method_metaclass     = newSVpvs("method_metaclass");
-    mop_wrap                 = newSVpvs("wrap");
-    mop_associated_metaclass = newSVpvs("associated_metaclass");
-
+    MOP_CALL_BOOT (boot_Class__MOP__Mixin__HasAttributes);
+    MOP_CALL_BOOT (boot_Class__MOP__Mixin__HasMethods);
     MOP_CALL_BOOT (boot_Class__MOP__Package);
+    MOP_CALL_BOOT (boot_Class__MOP__Mixin__AttributeCore);
+    MOP_CALL_BOOT (boot_Class__MOP__Method);
+    MOP_CALL_BOOT (boot_Class__MOP__Method__Inlined);
+    MOP_CALL_BOOT (boot_Class__MOP__Method__Generated);
     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);
 
 # use prototype here to be compatible with get_code_info from Sub::Identify
 void
@@ -45,23 +78,23 @@ get_code_info(coderef)
         char *pkg  = NULL;
         char *name = NULL;
     PPCODE:
+        SvGETMAGIC(coderef);
         if (mop_get_code_info(coderef, &pkg, &name)) {
             EXTEND(SP, 2);
-            PUSHs(newSVpv(pkg, 0));
-            PUSHs(newSVpv(name, 0));
+            mPUSHs(newSVpv(pkg, 0));
+            mPUSHs(newSVpv(name, 0));
         }
 
-# This is some pretty grotty logic. It _should_ be parallel to the
-# pure Perl version in lib/Class/MOP.pm, so if you want to understand
-# it we suggest you start there.
 void
-is_class_loaded(klass=&PL_sv_undef)
+is_class_loaded(klass, options=NULL)
     SV *klass
+    HV *options
     PREINIT:
         HV *stash;
         bool found_method = FALSE;
     PPCODE:
-        if (!SvPOK(klass) || !SvCUR(klass)) {
+        SvGETMAGIC(klass);
+        if (!(SvPOKp(klass) && SvCUR(klass))) { /* XXX: SvPOK does not work with magical scalars */
             XSRETURN_NO;
         }
 
@@ -70,6 +103,15 @@ is_class_loaded(klass=&PL_sv_undef)
             XSRETURN_NO;
         }
 
+        if (options && hv_exists_ent(options, KEY_FOR(_version), HASH_FOR(_version))) {
+            HE *required_version = hv_fetch_ent(options, KEY_FOR(_version), 0, HASH_FOR(_version));
+            if (check_version (klass, HeVAL(required_version))) {
+                XSRETURN_YES;
+            }
+
+            XSRETURN_NO;
+        }
+
         if (hv_exists_ent (stash, KEY_FOR(VERSION), HASH_FOR(VERSION))) {
             HE *version = hv_fetch_ent(stash, KEY_FOR(VERSION), 0, HASH_FOR(VERSION));
             SV *version_sv;
@@ -89,7 +131,7 @@ is_class_loaded(klass=&PL_sv_undef)
 
         if (hv_exists_ent (stash, KEY_FOR(ISA), HASH_FOR(ISA))) {
             HE *isa = hv_fetch_ent(stash, KEY_FOR(ISA), 0, HASH_FOR(ISA));
-            if (isa && HeVAL(isa) && GvAV(HeVAL(isa))) {
+            if (isa && HeVAL(isa) && GvAV(HeVAL(isa)) && av_len(GvAV(HeVAL(isa))) != -1) {
                 XSRETURN_YES;
             }
         }