]> git.saurik.com Git - cycript.git/commitdiff
Use variadic templates to better organize Classes.
authorJay Freeman (saurik) <saurik@saurik.com>
Thu, 31 Dec 2015 03:48:06 +0000 (19:48 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Thu, 31 Dec 2015 03:48:06 +0000 (19:48 -0800)
Execute.cpp
Internal.hpp
ObjectiveC/Internal.hpp
ObjectiveC/Library.mm
Utility.hpp [new file with mode: 0644]

index 41550baee3cff3c8e133bbbcd0ac11c8c49d1821..dfc015835c958979b4586bc5e843d9b116a6a5aa 100644 (file)
@@ -168,12 +168,8 @@ static JSObjectRef CYObjectMakeArray(JSContextRef context, size_t length, const
 
 static JSClassRef All_;
 static JSClassRef Context_;
-static JSClassRef CArray_;
-static JSClassRef CString_;
 JSClassRef Functor_;
 static JSClassRef Global_;
-static JSClassRef Pointer_;
-static JSClassRef Struct_;
 
 JSStringRef Array_s;
 JSStringRef cy_s;
@@ -222,91 +218,82 @@ struct Context :
 };
 
 struct CArray :
-    CYOwned
+    CYValue_<CArray, void *>
 {
+    CYProtect owner_;
     Type_privateData *type_;
     size_t length_;
 
-    CArray(void *value, JSContextRef context, JSObjectRef owner, size_t length, const sig::Type &type, ffi_type *ffi) :
-        CYOwned(value, context, owner),
+    CArray(void *value, size_t length, const sig::Type &type, ffi_type *ffi, JSContextRef context, JSObjectRef owner) :
+        CYValue_(value),
+        owner_(context, owner),
         type_(new(*pool_) Type_privateData(type, ffi)),
         length_(length)
     {
+        if (owner == NULL) {
+            size_t size(ffi->size * length);
+            void *copy(pool_->malloc<void>(size, ffi->alignment));
+            memcpy(copy, GetValue(), size);
+            value_ = copy;
+        }
     }
 };
 
 struct CString :
-    CYOwned
+    CYValue_<CString, char *>
 {
+    CYProtect owner_;
+
     CString(char *value, JSContextRef context, JSObjectRef owner) :
-        CYOwned(value, context, owner)
+        CYValue_(value),
+        owner_(context, owner)
     {
+        if (owner == NULL)
+            value_ = pool_->strdup(GetValue());
     }
 };
 
 struct Pointer :
-    CYOwned
+    CYValue_<Pointer, void *>
 {
+    CYProtect owner_;
     Type_privateData *type_;
 
-    Pointer(void *value, JSContextRef context, JSObjectRef owner, const sig::Type &type) :
-        CYOwned(value, context, owner),
+    Pointer(void *value, const sig::Type &type, JSContextRef context, JSObjectRef owner) :
+        CYValue_(value),
+        owner_(context, owner),
         type_(new(*pool_) Type_privateData(type))
     {
     }
 
-    Pointer(void *value, JSContextRef context, JSObjectRef owner, const char *encoding) :
-        CYOwned(value, context, owner),
+    Pointer(void *value, const char *encoding, JSContextRef context, JSObjectRef owner) :
+        CYValue_(value),
+        owner_(context, owner),
         type_(new(*pool_) Type_privateData(encoding))
     {
     }
 };
 
 struct Struct_privateData :
-    CYOwned
+    CYValue_<Struct_privateData, void *>
 {
+    CYProtect owner_;
     Type_privateData *type_;
 
-    Struct_privateData(void *value, JSContextRef context, JSObjectRef owner, const sig::Type &type, ffi_type *ffi) :
-        CYOwned(value, context, owner),
+    Struct_privateData(void *value, const sig::Type &type, ffi_type *ffi, JSContextRef context, JSObjectRef owner) :
+        CYValue_(value),
+        owner_(context, owner),
         type_(new(*pool_) Type_privateData(type, ffi))
     {
+        if (owner == NULL) {
+            size_t size(ffi->size);
+            void *copy(pool_->malloc<void>(size, ffi->alignment));
+            memcpy(copy, GetValue(), size);
+            value_ = copy;
+        }
     }
 };
 
-JSObjectRef CYMakeCArray(JSContextRef context, void *data, size_t length, const sig::Type &type, ffi_type *ffi, JSObjectRef owner) {
-    CArray *internal(new CArray(data, context, owner, length, type, ffi));
-
-    if (owner == NULL) {
-        size_t size(ffi->size * length);
-        void *copy(internal->pool_->malloc<void>(size, ffi->alignment));
-        memcpy(copy, internal->value_, size);
-        internal->value_ = copy;
-    }
-
-    return JSObjectMake(context, CArray_, internal);
-}
-
-JSObjectRef CYMakeCString(JSContextRef context, char *pointer, JSObjectRef owner) {
-    CString *internal(new CString(pointer, context, owner));
-    if (owner == NULL)
-        internal->value_ = internal->pool_->strdup(static_cast<const char *>(internal->value_));
-    return JSObjectMake(context, CString_, internal);
-}
-
-JSObjectRef CYMakeStruct(JSContextRef context, void *data, const sig::Type &type, ffi_type *ffi, JSObjectRef owner) {
-    Struct_privateData *internal(new Struct_privateData(data, context, owner, type, ffi));
-
-    if (owner == NULL) {
-        size_t size(ffi->size);
-        void *copy(internal->pool_->malloc<void>(size, ffi->alignment));
-        memcpy(copy, internal->value_, size);
-        internal->value_ = copy;
-    }
-
-    return JSObjectMake(context, Struct_, internal);
-}
-
 static void *CYCastSymbol(const char *name) {
     for (CYHook *hook : GetHooks())
         if (hook->CastSymbol != NULL)
@@ -641,13 +628,7 @@ static JSValueRef String_callAsFunction_toCYON(JSContextRef context, JSObjectRef
 } CYCatch(NULL) }
 
 JSObjectRef CYMakePointer(JSContextRef context, void *pointer, const sig::Type &type, ffi_type *ffi, JSObjectRef owner) {
-    Pointer *internal(new Pointer(pointer, context, owner, type));
-    return JSObjectMake(context, Pointer_, internal);
-}
-
-JSObjectRef CYMakePointer(JSContextRef context, void *pointer, const char *encoding, JSObjectRef owner) {
-    Pointer *internal(new Pointer(pointer, context, owner, encoding));
-    return JSObjectMake(context, Pointer_, internal);
+    return Pointer::Make(context, pointer, type, context, owner);
 }
 
 static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), bool variadic, const sig::Signature &signature) {
@@ -676,7 +657,7 @@ void *CYCastPointer_(JSContextRef context, JSValueRef value, bool *guess) {
             return NULL;
         case kJSTypeObject: {
             JSObjectRef object((JSObjectRef) value);
-            if (JSValueIsObjectOfClass(context, value, Pointer_)) {
+            if (JSValueIsObjectOfClass(context, value, Pointer::Class_)) {
                 Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(object)));
                 return internal->value_;
             }
@@ -856,7 +837,7 @@ JSValueRef Unknown::FromFFI(JSContextRef context, ffi_type *ffi, void *data, boo
 
 JSValueRef String::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
     if (char *value = *reinterpret_cast<char **>(data))
-        return CYMakeCString(context, value, owner);
+        return CString::Make(context, value, context, owner);
     return CYJSNull(context);
 }
 
@@ -871,11 +852,11 @@ JSValueRef Pointer::FromFFI(JSContextRef context, ffi_type *ffi, void *data, boo
 }
 
 JSValueRef Array::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
-    return CYMakeCArray(context, data, size, type, ffi->elements[0], owner);
+    return CArray::Make(context, data, size, type, ffi->elements[0], context, owner);
 }
 
 JSValueRef Aggregate::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
-    return CYMakeStruct(context, data, *this, ffi, owner);
+    return Struct_privateData::Make(context, data, *this, ffi, context, owner);
 }
 
 JSValueRef Function::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
@@ -978,26 +959,24 @@ static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, bool va
 static JSValueRef CString_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     CYPool pool;
     CString *internal(reinterpret_cast<CString *>(JSObjectGetPrivate(object)));
-    char *string(static_cast<char *>(internal->value_));
 
     ssize_t offset;
     if (!CYGetOffset(pool, context, property, offset))
         return NULL;
 
-    return CYCastJSValue(context, CYJSString(CYUTF8String(&string[offset], 1)));
+    return CYCastJSValue(context, CYJSString(CYUTF8String(&internal->GetValue()[offset], 1)));
 } CYCatch(NULL) }
 
 static bool CString_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry {
     CYPool pool;
     CString *internal(reinterpret_cast<CString *>(JSObjectGetPrivate(object)));
-    char *string(static_cast<char *>(internal->value_));
 
     ssize_t offset;
     if (!CYGetOffset(pool, context, property, offset))
         return false;
 
     const char *data(CYPoolCString(pool, context, value));
-    string[offset] = *data;
+    internal->GetValue()[offset] = *data;
     return true;
 } CYCatch(false) }
 
@@ -1080,7 +1059,7 @@ static JSValueRef CArray_getProperty(JSContextRef context, JSObjectRef object, J
     if (JSStringIsEqual(property, length_s))
         return CYCastJSValue(context, internal->length_);
     Type_privateData *typical(internal->type_);
-    JSObjectRef owner(internal->GetOwner() ?: object);
+    JSObjectRef owner(internal->owner_ ?: object);
     return Offset_getProperty(pool, context, property, internal->value_, typical, owner);
 } CYCatch(NULL) }
 
@@ -1103,7 +1082,7 @@ static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object,
         return CYMakeFunctor(context, reinterpret_cast<void (*)()>(internal->value_), function->variadic, function->signature);
     }
 
-    JSObjectRef owner(internal->GetOwner() ?: object);
+    JSObjectRef owner(internal->owner_ ?: object);
     return Offset_getProperty(pool, context, property, internal->value_, typical, owner);
 } CYCatch(NULL) }
 
@@ -1137,7 +1116,7 @@ static JSValueRef Struct_getProperty(JSContextRef context, JSObjectRef object, J
     if (!Index_(pool, context, internal, property, index, base))
         return NULL;
 
-    JSObjectRef owner(internal->GetOwner() ?: object);
+    JSObjectRef owner(internal->owner_ ?: object);
 
     return type->signature.elements[index].type->FromFFI(context, typical->GetFFI()->elements[index], base, false, owner);
 } CYCatch(NULL) }
@@ -1609,13 +1588,13 @@ static JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t
 
 static JSValueRef CArray_callAsFunction_toPointer(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     CArray *internal(reinterpret_cast<CArray *>(JSObjectGetPrivate(_this)));
-    JSObjectRef owner(internal->GetOwner() ?: object);
+    JSObjectRef owner(internal->owner_ ?: object);
     return CYMakePointer(context, internal->value_, *internal->type_->type_, NULL, owner);
 } CYCatch(NULL) }
 
 static JSValueRef CString_callAsFunction_toPointer(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     CString *internal(reinterpret_cast<CString *>(JSObjectGetPrivate(_this)));
-    JSObjectRef owner(internal->GetOwner() ?: object);
+    JSObjectRef owner(internal->owner_ ?: object);
     return CYMakePointer(context, internal->value_, sig::Primitive<char>(), NULL, owner);
 } CYCatch(NULL) }
 
@@ -1691,8 +1670,7 @@ static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRe
 
 static JSValueRef CString_getProperty_length(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     CString *internal(reinterpret_cast<CString *>(JSObjectGetPrivate(object)));
-    char *string(static_cast<char *>(internal->value_));
-    return CYCastJSValue(context, strlen(string));
+    return CYCastJSValue(context, strlen(internal->GetValue()));
 } CYCatch(NULL) }
 
 static JSValueRef CString_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
@@ -1712,8 +1690,8 @@ static JSValueRef Pointer_getProperty_$cyt(JSContextRef context, JSObjectRef obj
 } CYCatch(NULL) }
 
 static JSValueRef CString_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(_this)));
-    const char *string(static_cast<const char *>(internal->value_));
+    CString *internal(reinterpret_cast<CString *>(JSObjectGetPrivate(_this)));
+    const char *string(internal->GetValue());
     std::ostringstream str;
     if (string == NULL)
         str << "NULL";
@@ -1726,9 +1704,8 @@ static JSValueRef CString_callAsFunction_toCYON(JSContextRef context, JSObjectRe
 } CYCatch(NULL) }
 
 static JSValueRef CString_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(_this)));
-    const char *string(static_cast<const char *>(internal->value_));
-    return CYCastJSValue(context, string);
+    CString *internal(reinterpret_cast<CString *>(JSObjectGetPrivate(_this)));
+    return CYCastJSValue(context, internal->GetValue());
 } CYCatch(NULL) }
 
 static JSValueRef Functor_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
@@ -1985,7 +1962,7 @@ void CYInitializeDynamic() {
     definition.getProperty = &CArray_getProperty;
     definition.setProperty = &CArray_setProperty;
     definition.finalize = &CYFinalize;
-    CArray_ = JSClassCreate(&definition);
+    CArray::Class_ = JSClassCreate(&definition);
 
     definition = kJSClassDefinitionEmpty;
     definition.className = "CString";
@@ -1994,7 +1971,7 @@ void CYInitializeDynamic() {
     definition.getProperty = &CString_getProperty;
     definition.setProperty = &CString_setProperty;
     definition.finalize = &CYFinalize;
-    CString_ = JSClassCreate(&definition);
+    CString::Class_ = JSClassCreate(&definition);
 
     definition = kJSClassDefinitionEmpty;
     definition.className = "Functor";
@@ -2012,7 +1989,7 @@ void CYInitializeDynamic() {
     definition.getProperty = &Pointer_getProperty;
     definition.setProperty = &Pointer_setProperty;
     definition.finalize = &CYFinalize;
-    Pointer_ = JSClassCreate(&definition);
+    Pointer::Class_ = JSClassCreate(&definition);
 
     definition = kJSClassDefinitionEmpty;
     definition.className = "Struct";
@@ -2022,7 +1999,7 @@ void CYInitializeDynamic() {
     definition.setProperty = &Struct_setProperty;
     definition.getPropertyNames = &Struct_getPropertyNames;
     definition.finalize = &CYFinalize;
-    Struct_ = JSClassCreate(&definition);
+    Struct_privateData::Class_ = JSClassCreate(&definition);
 
     definition = kJSClassDefinitionEmpty;
     definition.className = "Type";
@@ -2257,11 +2234,11 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) {
     CYSetProperty(context, cycript, CYJSString("compile"), &Cycript_compile_callAsFunction);
     CYSetProperty(context, cycript, CYJSString("gc"), &Cycript_gc_callAsFunction);
 
-    JSObjectRef CArray(JSObjectMakeConstructor(context, CArray_, &CArray_new));
+    JSObjectRef CArray(JSObjectMakeConstructor(context, CArray::Class_, &CArray_new));
     CYSetPrototype(context, CYCastJSObject(context, CYGetProperty(context, CArray, prototype_s)), Array_prototype);
     CYSetProperty(context, cycript, CYJSString("CArray"), CArray);
 
-    JSObjectRef CString(JSObjectMakeConstructor(context, CString_, &CString_new));
+    JSObjectRef CString(JSObjectMakeConstructor(context, CString::Class_, &CString_new));
     CYSetPrototype(context, CYCastJSObject(context, CYGetProperty(context, CString, prototype_s)), String_prototype);
     CYSetProperty(context, cycript, CYJSString("CString"), CString);
 
@@ -2269,7 +2246,7 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) {
     CYSetPrototype(context, CYCastJSObject(context, CYGetProperty(context, Functor, prototype_s)), Function_prototype);
     CYSetProperty(context, cycript, CYJSString("Functor"), Functor);
 
-    CYSetProperty(context, cycript, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new));
+    CYSetProperty(context, cycript, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer::Class_, &Pointer_new));
     CYSetProperty(context, cycript, CYJSString("Type"), JSObjectMakeConstructor(context, Type_privateData::Class_, &Type_new));
 
     JSObjectRef modules(JSObjectMake(context, NULL, NULL));
index 3c5d5f59bde3d5d7a9e0b96adc70a68ecd0c32c3..9819b53352ef6e9b165e014dd1488bff8600163a 100644 (file)
@@ -30,7 +30,9 @@
 #include <JavaScriptCore/JSObjectRef.h>
 #include <JavaScriptCore/JSValueRef.h>
 
+#include "JavaScript.hpp"
 #include "Pooling.hpp"
+#include "Utility.hpp"
 
 JSGlobalContextRef CYGetJSContext(JSContextRef context);
 sig::Type *Structor_(CYPool &pool, sig::Aggregate *aggregate);
@@ -110,32 +112,71 @@ struct CYValue :
     }
 };
 
-struct CYOwned :
+template <typename Internal_, typename Value_>
+struct CYValue_ :
     CYValue
 {
+    static JSClassRef Class_;
+    static Type_privateData *Type_;
+
+    using CYValue::CYValue;
+
+    _finline Value_ GetValue() const {
+        return reinterpret_cast<Value_>(value_);
+    }
+
+    virtual Type_privateData *GetType() const {
+        return Type_;
+    }
+
+    _finline JSValueRef GetPrototype(JSContextRef context) const {
+        return NULL;
+    }
+
+    template <typename... Args_>
+    _finline static JSClassRef GetClass(Args_ &&... args) {
+        return Class_;
+    }
+
+    template <typename... Args_>
+    static JSObjectRef Make(JSContextRef context, Args_ &&... args) {
+        Internal_ *internal(new Internal_(cy::Forward<Args_>(args)...));
+        JSObjectRef object(JSObjectMake(context, Internal_::GetClass(cy::Forward<Args_>(args)...), internal));
+        if (JSValueRef prototype = internal->GetPrototype(context))
+            CYSetPrototype(context, object, prototype);
+        return object;
+    }
+};
+
+template <typename Internal_, typename Value_>
+JSClassRef CYValue_<Internal_, Value_>::Class_;
+
+template <typename Internal_, typename Value_>
+Type_privateData *CYValue_<Internal_, Value_>::Type_;
+
+struct CYProtect {
   private:
     JSGlobalContextRef context_;
-    JSObjectRef owner_;
+    JSObjectRef object_;
 
   public:
-    CYOwned(void *value, JSContextRef context, JSObjectRef owner) :
-        CYValue(value),
+    CYProtect(JSContextRef context, JSObjectRef object) :
         context_(CYGetJSContext(context)),
-        owner_(owner)
+        object_(object)
     {
         //XXX:JSGlobalContextRetain(context_);
-        if (owner_ != NULL)
-            JSValueProtect(context_, owner_);
+        if (object_ != NULL)
+            JSValueProtect(context_, object_);
     }
 
-    virtual ~CYOwned() {
-        if (owner_ != NULL)
-            JSValueUnprotect(context_, owner_);
+    ~CYProtect() {
+        if (object_ != NULL)
+            JSValueUnprotect(context_, object_);
         //XXX:JSGlobalContextRelease(context_);
     }
 
-    JSObjectRef GetOwner() const {
-        return owner_;
+    operator JSObjectRef() const {
+        return object_;
     }
 };
 
index 9cffb48ece8086176a42a0cb867b156990564615..49461489d2a06b5825b1f560d1fc6741f066d53c 100644 (file)
 #include "../Internal.hpp"
 
 struct Selector_privateData :
-    CYValue
+    CYValue_<Selector_privateData, SEL>
 {
     _finline Selector_privateData(SEL value) :
-        CYValue(value)
+        CYValue_(value)
     {
     }
-
-    _finline SEL GetValue() const {
-        return reinterpret_cast<SEL>(value_);
-    }
-
-    virtual Type_privateData *GetType() const;
 };
 
 struct Instance :
-    CYValue
+    CYValue_<Instance, id>
 {
     enum Flags {
         None          = 0,
@@ -52,70 +46,52 @@ struct Instance :
 
     Flags flags_;
 
-    _finline Instance(id value, Flags flags) :
-        CYValue(value),
-        flags_(flags)
-    {
-    }
-
+    Instance(id value, Flags flags);
     virtual ~Instance();
 
-    static JSObjectRef Make(JSContextRef context, id object, Flags flags = None);
+    JSValueRef GetPrototype(JSContextRef context) const;
 
-    _finline id GetValue() const {
-        return reinterpret_cast<id>(value_);
-    }
+    static JSClassRef GetClass(id value, Flags flags);
 
     _finline bool IsUninitialized() const {
         return (flags_ & Uninitialized) != 0;
     }
-
-    virtual Type_privateData *GetType() const;
 };
 
 namespace cy {
 struct Super :
-    Instance
+    CYValue_<Super, id>
 {
     Class class_;
 
     _finline Super(id value, Class _class) :
-        Instance(value, Instance::Permanent),
+        CYValue_(value),
         class_(_class)
     {
     }
-
-    static JSObjectRef Make(JSContextRef context, id object, Class _class);
 }; }
 
 struct Messages :
-    CYValue
+    CYValue_<Messages, Class>
 {
     _finline Messages(Class value) :
-        CYValue(value)
+        CYValue_(value)
     {
     }
 
-    static JSObjectRef Make(JSContextRef context, Class _class);
-
-    _finline Class GetValue() const {
-        return reinterpret_cast<Class>(value_);
-    }
+    JSValueRef GetPrototype(JSContextRef context) const;
 };
 
 struct Internal :
-    CYOwned
+    CYValue_<Internal, id>
 {
+    CYProtect owner_;
+
     _finline Internal(id value, JSContextRef context, JSObjectRef owner) :
-        CYOwned(value, context, owner)
+        CYValue_(value),
+        owner_(context, owner)
     {
     }
-
-    static JSObjectRef Make(JSContextRef context, id object, JSObjectRef owner);
-
-    _finline id GetValue() const {
-        return reinterpret_cast<id>(value_);
-    }
 };
 
 #endif/*CYCRIPT_OBJECTIVEC_INTERNAL_HPP*/
index a2a3190d3b59b301cd93aaab92fdd1769cab1816..01f924092667f5a87dfd56c90674ac432811908f 100644 (file)
@@ -243,22 +243,14 @@ bool CYGetOffset(CYPool &pool, JSContextRef context, NSString *value, ssize_t &i
     return CYGetOffset(CYPoolCString(pool, context, value), index);
 }
 
-static JSClassRef Instance_;
-
 static JSClassRef ArrayInstance_;
 static JSClassRef BooleanInstance_;
+static JSClassRef ClassInstance_;
 static JSClassRef FunctionInstance_;
 static JSClassRef NumberInstance_;
 static JSClassRef ObjectInstance_;
 static JSClassRef StringInstance_;
 
-static JSClassRef Class_;
-static JSClassRef Internal_;
-static JSClassRef Message_;
-static JSClassRef Messages_;
-static JSClassRef Selector_;
-static JSClassRef Super_;
-
 static JSClassRef ObjectiveC_Classes_;
 static JSClassRef ObjectiveC_Constants_;
 static JSClassRef ObjectiveC_Protocols_;
@@ -285,24 +277,13 @@ static Class NSString_;
 static Class NSZombie_;
 static Class Object_;
 
-static Type_privateData *Object_type;
-static Type_privateData *Selector_type;
-
-Type_privateData *Instance::GetType() const {
-    return Object_type;
-}
-
-Type_privateData *Selector_privateData::GetType() const {
-    return Selector_type;
-}
-
 static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception);
 
 JSValueRef CYGetClassPrototype(JSContextRef context, Class self, bool meta) {
     if (self == nil)
         return CYGetCachedObject(context, CYJSString("Instance_prototype"));
     else if (meta && !class_isMetaClass(self))
-        return CYGetCachedObject(context, CYJSString("Class_prototype"));
+        return CYGetCachedObject(context, CYJSString("ClassInstance_prototype"));
 
     JSObjectRef global(CYGetGlobalObject(context));
     JSObjectRef cy(CYCastJSObject(context, CYGetProperty(context, global, cy_s)));
@@ -348,23 +329,12 @@ _finline JSValueRef CYGetClassPrototype(JSContextRef context, Class self) {
     return CYGetClassPrototype(context, self, class_isMetaClass(self));
 }
 
-JSObjectRef Messages::Make(JSContextRef context, Class _class) {
-    JSObjectRef value(JSObjectMake(context, Messages_, new Messages(_class)));
-    if (Class super = class_getSuperclass(_class))
-        CYSetPrototype(context, value, Messages::Make(context, super));
-    return value;
-}
-
-JSObjectRef Internal::Make(JSContextRef context, id object, JSObjectRef owner) {
-    return JSObjectMake(context, Internal_, new Internal(object, context, owner));
+JSValueRef Messages::GetPrototype(JSContextRef context) const {
+    if (Class super = class_getSuperclass(GetValue()))
+        return Messages::Make(context, super);
+    return NULL;
 }
 
-namespace cy {
-JSObjectRef Super::Make(JSContextRef context, id object, Class _class) {
-    JSObjectRef value(JSObjectMake(context, Super_, new Super(object, _class)));
-    return value;
-} }
-
 bool CYIsKindOfClass(id object, Class _class) {
     for (Class isa(object_getClass(object)); isa != NULL; isa = class_getSuperclass(isa))
         if (isa == _class)
@@ -372,10 +342,20 @@ bool CYIsKindOfClass(id object, Class _class) {
     return false;
 }
 
-JSObjectRef Instance::Make(JSContextRef context, id object, Flags flags) {
-    JSObjectRef value(JSObjectMake(context, CYIsKindOfClass(object, NSBlock_) ? FunctionInstance_ : Instance_, new Instance(object, flags)));
-    CYSetPrototype(context, value, CYGetClassPrototype(context, object_getClass(object)));
-    return value;
+JSValueRef Instance::GetPrototype(JSContextRef context) const {
+    return CYGetClassPrototype(context, object_getClass(GetValue()));
+}
+
+JSClassRef Instance::GetClass(id object, Flags flags) {
+    return CYIsKindOfClass(object, NSBlock_) ? FunctionInstance_ : Instance::Class_;
+}
+
+Instance::Instance(id value, Flags flags) :
+    CYValue_(value),
+    flags_(flags)
+{
+    if ((flags & Instance::Permanent) == 0)
+        value_ = [GetValue() retain];
 }
 
 Instance::~Instance() {
@@ -386,15 +366,21 @@ Instance::~Instance() {
 struct Message_privateData :
     cy::Functor
 {
+    static JSClassRef Class_;
+
     SEL sel_;
 
-    Message_privateData(SEL sel, const char *type, IMP value = NULL) :
+    Message_privateData(SEL sel, const char *type, IMP value) :
         cy::Functor(reinterpret_cast<void (*)()>(value), type),
         sel_(sel)
     {
     }
+
+    static JSObjectRef Make(JSContextRef context, SEL sel, const char *type, IMP value);
 };
 
+JSClassRef Message_privateData::Class_;
+
 JSObjectRef CYMakeInstance(JSContextRef context, id object, Instance::Flags flags = Instance::None) {
     _assert(object != nil);
 
@@ -406,9 +392,6 @@ JSObjectRef CYMakeInstance(JSContextRef context, id object, Instance::Flags flag
             return instance;
 #endif
 
-    if ((flags & Instance::Permanent) == 0)
-        object = [object retain];
-
     JSObjectRef instance(Instance::Make(context, object, flags));
 
 #ifdef __APPLE__
@@ -626,7 +609,7 @@ struct PropertyAttributes {
 /* }}} */
 
 _finline bool CYJSValueIsNSObject(JSContextRef context, JSValueRef value) {
-    return JSValueIsObjectOfClass(context, value, Instance_) || JSValueIsObjectOfClass(context, value, FunctionInstance_);
+    return JSValueIsObjectOfClass(context, value, Instance::Class_) || JSValueIsObjectOfClass(context, value, FunctionInstance_);
 }
 
 _finline bool CYJSValueIsInstanceOfCachedConstructor(JSContextRef context, JSValueRef value, JSStringRef cache) {
@@ -1483,19 +1466,14 @@ JSValueRef CYCastJSValue(JSContextRef context, NSObject *value) {
 
 @end
 
-static JSObjectRef CYMakeSelector(JSContextRef context, SEL sel) {
-    Selector_privateData *internal(new Selector_privateData(sel));
-    return JSObjectMake(context, Selector_, internal);
-}
-
 static JSValueRef CYCastJSValue(JSContextRef context, SEL sel) {
     if (sel == NULL)
         return CYJSNull(context);
-    return CYMakeSelector(context, sel);
+    return Selector_privateData::Make(context, sel);
 }
 
 static SEL CYCastSEL(JSContextRef context, JSValueRef value) {
-    if (JSValueIsObjectOfClass(context, value, Selector_)) {
+    if (JSValueIsObjectOfClass(context, value, Selector_privateData::Class_)) {
         Selector_privateData *internal(reinterpret_cast<Selector_privateData *>(JSObjectGetPrivate((JSObjectRef) value)));
         return reinterpret_cast<SEL>(internal->value_);
     } else {
@@ -1525,7 +1503,7 @@ static NSBlock *CYCastNSBlock(CYPool &pool, JSContextRef context, JSValueRef val
     if (JSValueIsObjectOfClass(context, object, FunctionInstance_))
         return reinterpret_cast<Instance *>(JSObjectGetPrivate(object))->GetValue();
 
-    if (JSValueIsObjectOfClass(context, object, Instance_)) {
+    if (JSValueIsObjectOfClass(context, object, Instance::Class_)) {
         _assert(reinterpret_cast<Instance *>(JSObjectGetPrivate(object))->GetValue() == nil);
         return nil;
     }
@@ -1628,9 +1606,9 @@ static JSValueRef MessageAdapter_(JSContextRef context, size_t count, JSValueRef
     return CYCallAsFunction(context, function, _this, count - 2, values + 2);
 }
 
-static JSObjectRef CYMakeMessage(JSContextRef context, SEL sel, IMP imp, const char *type) {
-    Message_privateData *internal(new Message_privateData(sel, type, imp));
-    return JSObjectMake(context, Message_, internal);
+JSObjectRef Message_privateData::Make(JSContextRef context, SEL sel, const char *type, IMP value) {
+    Message_privateData *internal(new Message_privateData(sel, type, value));
+    return JSObjectMake(context, Message_privateData::Class_, internal);
 }
 
 static IMP CYMakeMessage(JSContextRef context, JSValueRef value, const char *encoding) {
@@ -1666,7 +1644,7 @@ static JSValueRef Messages_getProperty(JSContextRef context, JSObjectRef object,
 
     if (SEL sel = sel_getUid(name))
         if (objc_method *method = class_getInstanceMethod(_class, sel))
-            return CYMakeMessage(context, sel, method_getImplementation(method), method_getTypeEncoding(method));
+            return Message_privateData::Make(context, sel, method_getTypeEncoding(method), method_getImplementation(method));
 
     return NULL;
 } CYCatch(NULL) }
@@ -1682,7 +1660,7 @@ static bool Messages_setProperty(JSContextRef context, JSObjectRef object, JSStr
     const char *type;
     IMP imp;
 
-    if (JSValueIsObjectOfClass(context, value, Message_)) {
+    if (JSValueIsObjectOfClass(context, value, Message_privateData::Class_)) {
         Message_privateData *message(reinterpret_cast<Message_privateData *>(JSObjectGetPrivate((JSObjectRef) value)));
         type = sig::Unparse(pool, &message->signature_);
         imp = reinterpret_cast<IMP>(message->GetValue());
@@ -1768,7 +1746,7 @@ static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object,
     id self(internal->GetValue());
 
     if (JSStringIsEqualToUTF8CString(property, "$cyi"))
-        return Internal::Make(context, self, object);
+        return Internal::Make(context, self, context, object);
 
     CYPool pool;
     NSString *name(CYCastNSString(&pool, context, property));
@@ -2121,7 +2099,7 @@ static void Internal_getPropertyNames(JSContextRef context, JSObjectRef object,
 
 static JSValueRef Internal_callAsFunction_$cya(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     Internal *internal(reinterpret_cast<Internal *>(JSObjectGetPrivate(object)));
-    return internal->GetOwner();
+    return internal->owner_;
 } CYCatch(NULL) }
 
 static bool ObjectiveC_Classes_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) {
@@ -2440,7 +2418,7 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje
     SEL _cmd;
     Class _class;
 
-    if (JSValueIsObjectOfClass(context, arguments[0], Super_)) {
+    if (JSValueIsObjectOfClass(context, arguments[0], cy::Super::Class_)) {
         cy::Super *internal(reinterpret_cast<cy::Super *>(JSObjectGetPrivate((JSObjectRef) arguments[0])));
         self = internal->GetValue();
         _class = internal->class_;;
@@ -2506,7 +2484,7 @@ static JSObjectRef Selector_new(JSContextRef context, JSObjectRef object, size_t
         throw CYJSError(context, "incorrect number of arguments to Selector constructor");
     CYPool pool;
     const char *name(CYPoolCString(pool, context, arguments[0]));
-    return CYMakeSelector(context, sel_registerName(name));
+    return Selector_privateData::Make(context, sel_registerName(name));
 } CYCatch(NULL) }
 
 static JSObjectRef Instance_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -2767,8 +2745,8 @@ JSValueRef NSCFType$cy$toJSON$inContext$(id self, SEL sel, JSValueRef key, JSCon
 void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry {
     CYPool &pool(CYGetGlobalPool());
 
-    Object_type = new(pool) Type_privateData(sig::Object());
-    Selector_type = new(pool) Type_privateData(sig::Selector());
+    Instance::Type_ = new(pool) Type_privateData(sig::Object());
+    Selector_privateData::Type_ = new(pool) Type_privateData(sig::Selector());
 
     NSArray_ = objc_getClass("NSArray");
     NSBlock_ = objc_getClass("NSBlock");
@@ -2807,7 +2785,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry {
     definition.callAsConstructor = &Instance_callAsConstructor;
     definition.hasInstance = &Instance_hasInstance;
     definition.finalize = &CYFinalize;
-    Instance_ = JSClassCreate(&definition);
+    Instance::Class_ = JSClassCreate(&definition);
 
     definition.className = "ArrayInstance";
     ArrayInstance_ = JSClassCreate(&definition);
@@ -2832,7 +2810,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry {
     definition = kJSClassDefinitionEmpty;
     definition.className = "Class";
     definition.staticFunctions = Class_staticFunctions;
-    Class_ = JSClassCreate(&definition);
+    ClassInstance_ = JSClassCreate(&definition);
 
     definition = kJSClassDefinitionEmpty;
     definition.className = "Internal";
@@ -2842,7 +2820,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry {
     definition.setProperty = &Internal_setProperty;
     definition.getPropertyNames = &Internal_getPropertyNames;
     definition.finalize = &CYFinalize;
-    Internal_ = JSClassCreate(&definition);
+    Internal::Class_ = JSClassCreate(&definition);
 
     definition = kJSClassDefinitionEmpty;
     definition.className = "Message";
@@ -2850,7 +2828,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry {
     definition.staticValues = cy::Functor::StaticValues;
     definition.callAsFunction = &Message_callAsFunction;
     definition.finalize = &CYFinalize;
-    Message_ = JSClassCreate(&definition);
+    Message_privateData::Class_ = JSClassCreate(&definition);
 
     definition = kJSClassDefinitionEmpty;
     definition.className = "Messages";
@@ -2859,7 +2837,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry {
     definition.setProperty = &Messages_setProperty;
     definition.getPropertyNames = &Messages_getPropertyNames;
     definition.finalize = &CYFinalize;
-    Messages_ = JSClassCreate(&definition);
+    Messages::Class_ = JSClassCreate(&definition);
 
     definition = kJSClassDefinitionEmpty;
     definition.className = "Selector";
@@ -2867,13 +2845,12 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry {
     definition.staticFunctions = Selector_staticFunctions;
     definition.callAsFunction = &Selector_callAsFunction;
     definition.finalize = &CYFinalize;
-    Selector_ = JSClassCreate(&definition);
+    Selector_privateData::Class_ = JSClassCreate(&definition);
 
     definition = kJSClassDefinitionEmpty;
     definition.className = "Super";
-    definition.staticFunctions = Internal_staticFunctions;
     definition.finalize = &CYFinalize;
-    Super_ = JSClassCreate(&definition);
+    cy::Super::Class_ = JSClassCreate(&definition);
 
     definition = kJSClassDefinitionEmpty;
     definition.className = "ObjectiveC::Classes";
@@ -2946,11 +2923,10 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry {
     CYSetProperty(context, ObjectiveC, CYJSString("images"), JSObjectMake(context, ObjectiveC_Images_, NULL));
 #endif
 
-    JSObjectRef Class(JSObjectMakeConstructor(context, Class_, NULL));
-    JSObjectRef Instance(JSObjectMakeConstructor(context, Instance_, &Instance_new));
-    JSObjectRef Message(JSObjectMakeConstructor(context, Message_, NULL));
-    JSObjectRef Selector(JSObjectMakeConstructor(context, Selector_, &Selector_new));
-    JSObjectRef Super(JSObjectMakeConstructor(context, Super_, &Super_new));
+    JSObjectRef Instance(JSObjectMakeConstructor(context, Instance::Class_, &Instance_new));
+    JSObjectRef Message(JSObjectMakeConstructor(context, Message_privateData::Class_, NULL));
+    JSObjectRef Selector(JSObjectMakeConstructor(context, Selector_privateData::Class_, &Selector_new));
+    JSObjectRef Super(JSObjectMakeConstructor(context, cy::Super::Class_, &Super_new));
 
     JSObjectRef Instance_prototype(CYCastJSObject(context, CYGetProperty(context, Instance, prototype_s)));
     CYSetProperty(context, cy, CYJSString("Instance_prototype"), Instance_prototype);
@@ -2967,6 +2943,12 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry {
     JSObjectRef Boolean_prototype(CYGetCachedObject(context, CYJSString("Boolean_prototype")));
     CYSetPrototype(context, BooleanInstance_prototype, Boolean_prototype);
 
+    JSObjectRef ClassInstance(JSObjectMakeConstructor(context, ClassInstance_, NULL));
+    JSObjectRef ClassInstance_prototype(CYCastJSObject(context, CYGetProperty(context, ClassInstance, prototype_s)));
+    CYSetProperty(context, cy, CYJSString("ClassInstance_prototype"), ClassInstance_prototype);
+    // XXX: this doesn't fit the pattern of the other ones; maybe it sort of should?
+    CYSetPrototype(context, ClassInstance_prototype, Instance_prototype);
+
     JSObjectRef FunctionInstance(JSObjectMakeConstructor(context, FunctionInstance_, NULL));
     JSObjectRef FunctionInstance_prototype(CYCastJSObject(context, CYGetProperty(context, FunctionInstance, prototype_s)));
     CYSetProperty(context, cy, CYJSString("FunctionInstance_prototype"), FunctionInstance_prototype);
@@ -2991,10 +2973,6 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry {
     JSObjectRef String_prototype(CYGetCachedObject(context, CYJSString("String_prototype")));
     CYSetPrototype(context, StringInstance_prototype, String_prototype);
 
-    JSObjectRef Class_prototype(CYCastJSObject(context, CYGetProperty(context, Class, prototype_s)));
-    CYSetProperty(context, cy, CYJSString("Class_prototype"), Class_prototype);
-    CYSetPrototype(context, Class_prototype, Instance_prototype);
-
     CYSetProperty(context, cycript, CYJSString("Instance"), Instance);
     CYSetProperty(context, cycript, CYJSString("Selector"), Selector);
     CYSetProperty(context, cycript, CYJSString("objc_super"), Super);
diff --git a/Utility.hpp b/Utility.hpp
new file mode 100644 (file)
index 0000000..c2aa4e3
--- /dev/null
@@ -0,0 +1,49 @@
+/* Cycript - Optimizing JavaScript Compiler/Runtime
+ * Copyright (C) 2009-2015  Jay Freeman (saurik)
+*/
+
+/* GNU Affero General Public License, Version 3 {{{ */
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**/
+/* }}} */
+
+#ifndef CYCRIPT_UTILITY_HPP
+#define CYCRIPT_UTILITY_HPP
+
+// XXX: this is required because Apple is bad at developer tools (I hate them so much)
+
+namespace cy {
+
+template <class T> struct is_lvalue_reference      { static const bool value = false; };
+template <class T> struct is_lvalue_reference<T &> { static const bool value = true; };
+
+template <class T> struct remove_reference       { typedef T type; };
+template <class T> struct remove_reference<T &>  { typedef T type; };
+template <class T> struct remove_reference<T &&> { typedef T type; };
+
+template <class T>
+inline T &&Forward(typename cy::remove_reference<T>::type &t) noexcept {
+    return static_cast<T &&>(t);
+}
+
+template <class T>
+inline T &&Forward(typename cy::remove_reference<T>::type &&t) noexcept {
+    static_assert(!cy::is_lvalue_reference<T>::value, "Can not forward an rvalue as an lvalue.");
+    return static_cast<T &&>(t);
+}
+
+}
+
+#endif/*CYCRIPT_UTILITY_HPP*/