Add is_instance_of() to MOP APIs for extentions
gfx [Fri, 28 Aug 2009 03:04:34 +0000 (12:04 +0900)]
mop.h
xs/MOP.xs

diff --git a/mop.h b/mop.h
index 82f4bd9..1c8ef31 100644 (file)
--- a/mop.h
+++ b/mop.h
@@ -50,6 +50,10 @@ SV *mop_call1(pTHX_ SV *const self, SV *const method, SV *const arg1);
 bool mop_is_class_loaded(pTHX_ SV*);
 #define is_class_loaded(klass) mop_is_class_loaded(aTHX_ klass)
 
+bool mop_is_instance_of(pTHX_ SV*, SV*);
+#define is_instance_of(sv, klass)     mop_is_instance_of(aTHX_ sv, klass)
+#define is_instance_of_pvs(sv, klass) mop_is_instance_of(aTHX_ sv, newSVpvs_flags(klass, SVs_TEMP))
+
 typedef enum {
     TYPE_FILTER_NONE,
     TYPE_FILTER_CODE,
index f3d9f17..ad2df5b 100644 (file)
--- a/xs/MOP.xs
+++ b/xs/MOP.xs
@@ -13,7 +13,30 @@ SV *mop_package_cache_flag;
 
 SV *mop_VERSION;
 SV *mop_ISA;
+SV *mop_isa;
 
+/* equivalent to "blessed($x) && $x->isa($klass)" */
+bool
+mop_is_instance_of(pTHX_ SV* const sv, SV* const klass){
+    assert(sv);
+    assert(klass);
+
+    if(SvROK(sv) && SvOBJECT(SvRV(sv)) && SvOK(klass)){
+        bool ok;
+
+        ENTER;
+        SAVETMPS;
+
+        ok = SvTRUEx(mop_call1(aTHX_ sv, mop_isa, klass));
+
+        FREETMPS;
+        LEAVE;
+
+        return FALSE;
+    }
+
+    return FALSE;
+}
 
 static bool
 find_method (const char *key, STRLEN keylen, SV *val, void *ud)
@@ -95,6 +118,7 @@ BOOT:
     mop_package_cache_flag   = MAKE_KEYSV(_package_cache_flag);
     mop_VERSION              = MAKE_KEYSV(VERSION);
     mop_ISA                  = MAKE_KEYSV(ISA);
+    mop_isa                  = MAKE_KEYSV(isa);
 
     MOP_CALL_BOOT (boot_Class__MOP__Package);
     MOP_CALL_BOOT (boot_Class__MOP__Class);
@@ -125,3 +149,11 @@ is_class_loaded(SV* klass = &PL_sv_undef)
 INIT:
     SvGETMAGIC(klass);
 
+
+
+#bool
+#is_instance_of(SV* sv, SV* klass)
+#INIT:
+#    SvGETMAGIC(sv);
+#    SvGETMAGIC(klass);
+#