]> git.saurik.com Git - cycript.git/commitdiff
Move x.type() to typeid(x) and implement variadic.
authorJay Freeman (saurik) <saurik@saurik.com>
Wed, 30 Dec 2015 03:22:58 +0000 (19:22 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Wed, 30 Dec 2015 03:22:58 +0000 (19:22 -0800)
20 files changed:
Decode.cpp
Execute.cpp
Internal.hpp
JavaScript.hpp
ObjectiveC/Library.mm
ObjectiveC/Syntax.hpp
Output.cpp
Parser.ypp.in
Replace.cpp
Scanner.lpp.in
Syntax.hpp
config.h.in
configure
configure.ac
libcycript.cy
modules/com/saurik/substrate/MS.cy
sig/copy.cpp
sig/ffi_type.cpp
sig/ffi_type.hpp
sig/types.hpp

index 2187f268c32dc230f01e2bbb9eea0296f1157036..8bda223cd36654724f55216e1959729cdf68fd53 100644 (file)
@@ -150,26 +150,26 @@ CYTypedIdentifier *Aggregate::Decode(CYPool &pool) const {
     return $ CYTypedIdentifier($ CYTypeStruct(identifier, $ CYStructTail(fields)));
 }
 
-CYTypedIdentifier *Function::Decode(CYPool &pool) const {
+CYTypedIdentifier *Callable::Decode(CYPool &pool) const {
     _assert(signature.count != 0);
-    CYTypedParameter *parameter(NULL);
+    CYTypedParameter *parameters(NULL);
     for (size_t i(signature.count - 1); i != 0; --i)
-        parameter = $ CYTypedParameter(CYDecodeType(pool, signature.elements[i].type), parameter);
-    return CYDecodeType(pool, signature.elements[0].type)->Modify($ CYTypeFunctionWith(parameter));
+        parameters = $ CYTypedParameter(CYDecodeType(pool, signature.elements[i].type), parameters);
+    return Modify(pool, CYDecodeType(pool, signature.elements[0].type), parameters);
+}
+
+CYTypedIdentifier *Function::Modify(CYPool &pool, CYTypedIdentifier *result, CYTypedParameter *parameters) const {
+    return result->Modify($ CYTypeFunctionWith(variadic, parameters));
+}
+
+CYTypedIdentifier *Block::Modify(CYPool &pool, CYTypedIdentifier *result, CYTypedParameter *parameters) const {
+    return result->Modify($ CYTypeBlockWith(parameters));
 }
 
 CYTypedIdentifier *Block::Decode(CYPool &pool) const {
     if (signature.count == 0)
         return $ CYTypedIdentifier($ CYTypeVariable("NSBlock"), $ CYTypePointerTo());
-    else {
-        _assert(signature.count != 1);
-        _assert(dynamic_cast<Object *>(signature.elements[1].type) != NULL);
-
-        CYTypedParameter *parameter(NULL);
-        for (size_t i(signature.count - 1); i != 0; --i)
-            parameter = $ CYTypedParameter(CYDecodeType(pool, signature.elements[i].type), parameter);
-        return CYDecodeType(pool, signature.elements[0].type)->Modify($ CYTypeBlockWith(parameter));
-    }
+    return Callable::Decode(pool);
 }
 
 }
index 7875d8800075ccc5ead7ef41f349b333d9f4e7bf..d25f7b686c2468fdee4f2c48dfc8a051b521f892 100644 (file)
@@ -178,6 +178,7 @@ static JSClassRef Struct_;
 JSStringRef Array_s;
 JSStringRef cy_s;
 JSStringRef cyi_s;
+JSStringRef cyt_s;
 JSStringRef length_s;
 JSStringRef message_s;
 JSStringRef name_s;
@@ -649,8 +650,8 @@ JSObjectRef CYMakePointer(JSContextRef context, void *pointer, const char *encod
     return JSObjectMake(context, Pointer_, internal);
 }
 
-static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const sig::Signature &signature) {
-    return JSObjectMake(context, Functor_, new cy::Functor(signature, function));
+static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), bool variadic, const sig::Signature &signature) {
+    return JSObjectMake(context, Functor_, new cy::Functor(function, variadic, signature));
 }
 
 static JSObjectRef CYMakeFunctor(JSContextRef context, const char *symbol, const char *encoding) {
@@ -658,7 +659,7 @@ static JSObjectRef CYMakeFunctor(JSContextRef context, const char *symbol, const
     if (function == NULL)
         return NULL;
 
-    cy::Functor *internal(new cy::Functor(encoding, function));
+    cy::Functor *internal(new cy::Functor(function, encoding));
     ++internal->count_;
     return JSObjectMake(context, Functor_, internal);
 }
@@ -876,7 +877,7 @@ JSValueRef Aggregate::FromFFI(JSContextRef context, ffi_type *ffi, void *data, b
 }
 
 JSValueRef Function::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
-    return CYMakeFunctor(context, reinterpret_cast<void (*)()>(data), signature);
+    return CYMakeFunctor(context, reinterpret_cast<void (*)()>(data), variadic, signature);
 }
 
 }
@@ -959,7 +960,7 @@ JSObjectRef CYGetCachedObject(JSContextRef context, JSStringRef name) {
     return CYCastJSObject(context, CYGetCachedValue(context, name));
 }
 
-static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, const sig::Signature &signature) {
+static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, bool variadic, const sig::Signature &signature) {
     JSObjectRef Function(CYGetCachedObject(context, CYJSString("Function")));
 
     bool function(_jsccall(JSValueIsInstanceOfConstructor, context, value, Function));
@@ -968,7 +969,7 @@ static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, const s
         return CYMakeFunctor(context, function, signature);
     } else {
         void (*function)()(CYCastPointer<void (*)()>(context, value));
-        return CYMakeFunctor(context, function, signature);
+        return CYMakeFunctor(context, function, variadic, signature);
     }
 }
 
@@ -1097,7 +1098,7 @@ static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object,
     if (sig::Function *function = dynamic_cast<sig::Function *>(typical->type_)) {
         if (!JSStringIsEqualToUTF8CString(property, "$cyi"))
             return NULL;
-        return CYMakeFunctor(context, reinterpret_cast<void (*)()>(internal->value_), function->signature);
+        return CYMakeFunctor(context, reinterpret_cast<void (*)()>(internal->value_), function->variadic, function->signature);
     }
 
     JSObjectRef owner(internal->GetOwner() ?: object);
@@ -1117,7 +1118,7 @@ static JSValueRef Struct_callAsFunction_$cya(JSContextRef context, JSObjectRef o
     return CYMakePointer(context, internal->value_, *typical->type_, typical->ffi_, _this);
 } CYCatch(NULL) }
 
-static JSValueRef Struct_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+static JSValueRef Struct_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(object)));
     return CYMakeType(context, *internal->type_->type_);
 } CYCatch(NULL) }
@@ -1181,23 +1182,62 @@ static void Struct_getPropertyNames(JSContextRef context, JSObjectRef object, JS
     }
 }
 
+static sig::Void Void_;
+static sig::Pointer PointerToVoid_(Void_);
+
+static sig::Type *CYGetType(CYPool &pool, JSContextRef context, JSValueRef value) {
+    if (JSValueIsNull(context, value))
+        return &PointerToVoid_;
+    JSObjectRef object(CYCastJSObject(context, value));
+    JSObjectRef type(CYCastJSObject(context, CYGetProperty(context, object, cyt_s)));
+    _assert(JSValueIsObjectOfClass(context, type, Type_privateData::Class_));
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(type)));
+    return internal->type_;
+}
+
 void CYCallFunction(CYPool &pool, JSContextRef context, ffi_cif *cif, void (*function)(), void *value, void **values) {
     ffi_call(cif, function, value, values);
 }
 
-JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, sig::Signature *signature, ffi_cif *cif, void (*function)()) {
-    if (setups + count != signature->count - 1)
-        throw CYJSError(context, "incorrect number of arguments to ffi function");
+JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, bool variadic, const sig::Signature &signature, ffi_cif *cif, void (*function)()) {
+    size_t have(setups + count);
+    size_t need(signature.count - 1);
+
+    if (have < need)
+        throw CYJSError(context, "insufficient number of arguments to ffi function");
+
+    ffi_cif corrected;
+    sig::Element *elements(signature.elements);
+
+    if (have > need) {
+        if (!variadic)
+            throw CYJSError(context, "exorbitant number of arguments to ffi function");
+
+        elements = new (pool) sig::Element[have + 1];
+        memcpy(elements, signature.elements, sizeof(sig::Element) * (need + 1));
+
+        for (size_t index(need); index != have; ++index) {
+            sig::Element &element(elements[index + 1]);
+            element.name = NULL;
+            element.offset = _not(size_t);
+            element.type = CYGetType(pool, context, arguments[index - setups]);
+        }
+
+        sig::Signature extended;
+        extended.elements = elements;
+        extended.count = have + 1;
+        sig::sig_ffi_cif(pool, signature.count, extended, &corrected);
+        cif = &corrected;
+    }
 
-    size_t size(setups + count);
-    void *values[size];
+    void *values[have];
     memcpy(values, setup, sizeof(void *) * setups);
 
-    for (size_t index(setups); index != size; ++index) {
-        sig::Element *element(&signature->elements[index + 1]);
+    for (size_t index(setups); index != have; ++index) {
+        sig::Element &element(elements[index + 1]);
         ffi_type *ffi(cif->arg_types[index]);
         values[index] = pool.malloc<uint8_t>(ffi->size, ffi->alignment);
-        element->type->PoolFFI(&pool, context, ffi, values[index], arguments[index - setups]);
+        element.type->PoolFFI(&pool, context, ffi, values[index], arguments[index - setups]);
     }
 
     uint8_t value[cif->rtype->size];
@@ -1209,13 +1249,13 @@ JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, voi
             call = hook->CallFunction;
 
     call(pool, context, cif, function, value, values);
-    return signature->elements[0].type->FromFFI(context, cif->rtype, value, initialize);
+    return signature.elements[0].type->FromFFI(context, cif->rtype, value, initialize);
 }
 
 static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     CYPool pool;
     cy::Functor *internal(reinterpret_cast<cy::Functor *>(JSObjectGetPrivate(object)));
-    return CYCallFunction(pool, context, 0, NULL, count, arguments, false, &internal->signature_, &internal->cif_, internal->GetValue());
+    return CYCallFunction(pool, context, 0, NULL, count, arguments, false, internal->variadic_, internal->signature_, &internal->cif_, internal->GetValue());
 } CYCatch(NULL) }
 
 static JSValueRef Pointer_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1231,13 +1271,6 @@ JSObjectRef CYMakeType(JSContextRef context, const sig::Type &type) {
     return JSObjectMake(context, Type_privateData::Class_, internal);
 }
 
-JSObjectRef CYMakeType(JSContextRef context, sig::Signature *signature) {
-    CYPool pool;
-    sig::Function type;
-    sig::Copy(pool, type.signature, *signature);
-    return CYMakeType(context, type);
-}
-
 extern "C" bool CYBridgeHash(CYPool &pool, CYUTF8String name, const char *&code, unsigned &flags) {
     sqlite3_stmt *statement;
 
@@ -1499,8 +1532,9 @@ static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef
 } CYCatch(NULL) }
 
 static JSValueRef Type_callAsFunction_functionWith(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
-    sig::Function type;
-    return Type_callAsFunction_$With(context, object, _this, count, arguments, type, exception);
+    bool variadic(count != 0 && JSValueIsNull(context, arguments[count - 1]));
+    sig::Function type(variadic);
+    return Type_callAsFunction_$With(context, object, _this, variadic ? count - 1 : count, arguments, type, exception);
 }
 
 static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1529,14 +1563,23 @@ static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object,
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
 
     if (sig::Function *function = dynamic_cast<sig::Function *>(internal->type_))
-        return CYMakeFunctor(context, arguments[0], function->signature);
+        return CYMakeFunctor(context, arguments[0], function->variadic, function->signature);
 
     CYPool pool;
     sig::Type *type(internal->type_);
     ffi_type *ffi(internal->GetFFI());
-    void *value(pool.malloc<void>(ffi->size, ffi->alignment));
-    type->PoolFFI(&pool, context, ffi, value, arguments[0]);
-    return type->FromFFI(context, ffi, value);
+
+    void *data(pool.malloc<void>(ffi->size, ffi->alignment));
+    type->PoolFFI(&pool, context, ffi, data, arguments[0]);
+    JSValueRef value(type->FromFFI(context, ffi, data));
+
+    if (JSValueGetType(context, value) == kJSTypeNumber) {
+        JSObjectRef typed(_jsccall(JSObjectCallAsConstructor, context, CYGetCachedObject(context, CYJSString("Number")), 1, &value));
+        CYSetProperty(context, typed, cyt_s, object, kJSPropertyAttributeDontEnum);
+        value = typed;
+    }
+
+    return value;
 } CYCatch(NULL) }
 
 static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1559,7 +1602,7 @@ static JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t
     const char *encoding(CYPoolCString(pool, context, arguments[1]));
     sig::Signature signature;
     sig::Parse(pool, &signature, encoding, &Structor_);
-    return CYMakeFunctor(context, arguments[0], signature);
+    return CYMakeFunctor(context, arguments[0], false, signature);
 } CYCatch(NULL) }
 
 static JSValueRef CArray_callAsFunction_toPointer(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1578,7 +1621,7 @@ static JSValueRef Functor_callAsFunction_$cya(JSContextRef context, JSObjectRef
     CYPool pool;
     cy::Functor *internal(reinterpret_cast<cy::Functor *>(JSObjectGetPrivate(_this)));
 
-    sig::Function type;
+    sig::Function type(internal->variadic_);
     sig::Copy(pool, type.signature, internal->signature_);
 
     return CYMakePointer(context, internal->value_, type, NULL, NULL);
@@ -1650,17 +1693,17 @@ static JSValueRef CString_getProperty_length(JSContextRef context, JSObjectRef o
     return CYCastJSValue(context, strlen(string));
 } CYCatch(NULL) }
 
-static JSValueRef CString_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+static JSValueRef CString_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     return CYMakeType(context, sig::String());
 } CYCatch(NULL) }
 
-static JSValueRef CArray_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+static JSValueRef CArray_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     CArray *internal(reinterpret_cast<CArray *>(JSObjectGetPrivate(object)));
     sig::Array type(*internal->type_->type_, internal->length_);
     return CYMakeType(context, type);
 } CYCatch(NULL) }
 
-static JSValueRef Pointer_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+static JSValueRef Pointer_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(object)));
     sig::Pointer type(*internal->type_->type_);
     return CYMakeType(context, type);
@@ -1686,9 +1729,12 @@ static JSValueRef CString_callAsFunction_toString(JSContextRef context, JSObject
     return CYCastJSValue(context, string);
 } CYCatch(NULL) }
 
-static JSValueRef Functor_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+static JSValueRef Functor_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     cy::Functor *internal(reinterpret_cast<cy::Functor *>(JSObjectGetPrivate(object)));
-    return CYMakeType(context, &internal->signature_);
+    CYPool pool;
+    sig::Function type(internal->variadic_);
+    sig::Copy(pool, type.signature, internal->signature_);
+    return CYMakeType(context, type);
 } CYCatch(NULL) }
 
 static JSValueRef Type_getProperty_alignment(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
@@ -1740,7 +1786,7 @@ static JSStaticFunction CArray_staticFunctions[4] = {
 };
 
 static JSStaticValue CArray_staticValues[2] = {
-    {"type", &CArray_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"$cyt", &CArray_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {NULL, NULL, NULL, 0}
 };
 
@@ -1755,7 +1801,7 @@ static JSStaticFunction CString_staticFunctions[6] = {
 
 static JSStaticValue CString_staticValues[3] = {
     {"length", &CString_getProperty_length, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {"type", &CString_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"$cyt", &CString_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {NULL, NULL, NULL, 0}
 };
 
@@ -1768,7 +1814,7 @@ static JSStaticFunction Pointer_staticFunctions[5] = {
 };
 
 static JSStaticValue Pointer_staticValues[2] = {
-    {"type", &Pointer_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"$cyt", &Pointer_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {NULL, NULL, NULL, 0}
 };
 
@@ -1778,7 +1824,7 @@ static JSStaticFunction Struct_staticFunctions[2] = {
 };
 
 static JSStaticValue Struct_staticValues[2] = {
-    {"type", &Struct_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"$cyt", &Struct_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {NULL, NULL, NULL, 0}
 };
 
@@ -1795,7 +1841,7 @@ namespace cy {
 }
 
 static JSStaticValue Functor_staticValues[2] = {
-    {"type", &Functor_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"$cyt", &Functor_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {NULL, NULL, NULL, 0}
 };
 
@@ -1993,6 +2039,7 @@ void CYInitializeDynamic() {
     Array_s = JSStringCreateWithUTF8CString("Array");
     cy_s = JSStringCreateWithUTF8CString("$cy");
     cyi_s = JSStringCreateWithUTF8CString("$cyi");
+    cyt_s = JSStringCreateWithUTF8CString("$cyt");
     length_s = JSStringCreateWithUTF8CString("length");
     message_s = JSStringCreateWithUTF8CString("message");
     name_s = JSStringCreateWithUTF8CString("name");
@@ -2269,6 +2316,8 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) {
     }
 #endif
 
+    CYSetProperty(context, String_prototype, cyt_s, CYMakeType(context, sig::String()), kJSPropertyAttributeDontEnum);
+
     CYSetProperty(context, cache, CYJSString("dlerror"), CYMakeFunctor(context, "dlerror", "*"), kJSPropertyAttributeDontEnum);
     CYSetProperty(context, cache, CYJSString("RTLD_DEFAULT"), CYCastJSValue(context, reinterpret_cast<intptr_t>(RTLD_DEFAULT)), kJSPropertyAttributeDontEnum);
     CYSetProperty(context, cache, CYJSString("dlsym"), CYMakeFunctor(context, "dlsym", "^v^v*"), kJSPropertyAttributeDontEnum);
index 0851dea225467b3a65ab0954d831cd6d2fb5a9cd..3c5d5f59bde3d5d7a9e0b96adc70a68ecd0c32c3 100644 (file)
@@ -77,7 +77,7 @@ struct Type_privateData :
             signature.count = 1;
 
             ffi_cif cif;
-            sig::sig_ffi_cif(*pool_, &signature, &cif);
+            sig::sig_ffi_cif(*pool_, false, signature, &cif);
 
             ffi_ = new(*pool_) ffi_type;
             *ffi_ = *cif.rtype;
@@ -145,22 +145,25 @@ struct Functor :
 {
   private:
     void set() {
-        sig::sig_ffi_cif(*pool_, &signature_, &cif_);
+        sig::sig_ffi_cif(*pool_, variadic_ ? signature_.count : 0, signature_, &cif_);
     }
 
   public:
+    bool variadic_;
     sig::Signature signature_;
     ffi_cif cif_;
 
-    Functor(const sig::Signature &signature, void (*value)()) :
-        CYValue(reinterpret_cast<void *>(value))
+    Functor(void (*value)(), bool variadic, const sig::Signature &signature) :
+        CYValue(reinterpret_cast<void *>(value)),
+        variadic_(variadic)
     {
         sig::Copy(*pool_, signature_, signature);
         set();
     }
 
-    Functor(const char *encoding, void (*value)()) :
-        CYValue(reinterpret_cast<void *>(value))
+    Functor(void (*value)(), const char *encoding) :
+        CYValue(reinterpret_cast<void *>(value)),
+        variadic_(false)
     {
         sig::Parse(*pool_, &signature_, encoding, &Structor_);
         set();
@@ -182,7 +185,7 @@ struct Closure_privateData :
     JSValueRef (*adapter_)(JSContextRef, size_t, JSValueRef[], JSObjectRef);
 
     Closure_privateData(JSContextRef context, JSObjectRef function, JSValueRef (*adapter)(JSContextRef, size_t, JSValueRef[], JSObjectRef), const sig::Signature &signature) :
-        cy::Functor(signature, NULL),
+        cy::Functor(NULL, false, signature),
         context_(CYGetJSContext(context)),
         function_(function),
         adapter_(adapter)
index 08020fee8a682833d2504eb7fedccb9b4ce2b936..a162d9a2a83a894bfb56659a95b506b623574bf0 100644 (file)
@@ -42,6 +42,7 @@
 extern JSStringRef Array_s;
 extern JSStringRef cy_s;
 extern JSStringRef cyi_s;
+extern JSStringRef cyt_s;
 extern JSStringRef length_s;
 extern JSStringRef message_s;
 extern JSStringRef name_s;
@@ -111,7 +112,7 @@ _finline Type_ CYCastPointer(JSContextRef context, JSValueRef value, bool *guess
 }
 
 void CYCallFunction(CYPool &pool, JSContextRef context, ffi_cif *cif, void (*function)(), void *value, void **values);
-JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, sig::Signature *signature, ffi_cif *cif, void (*function)());
+JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, bool variadic, const sig::Signature &signature, ffi_cif *cif, void (*function)());
 
 bool CYIsCallable(JSContextRef context, JSValueRef value);
 JSValueRef CYCallAsFunction(JSContextRef context, JSObjectRef function, JSObjectRef _this, size_t count, const JSValueRef arguments[]);
@@ -138,7 +139,6 @@ struct CYRegisterHook {
 JSObjectRef CYMakePointer(JSContextRef context, void *pointer, const sig::Type &type, ffi_type *ffi, JSObjectRef owner);
 
 JSObjectRef CYMakeType(JSContextRef context, const sig::Type &type);
-JSObjectRef CYMakeType(JSContextRef context, sig::Signature *signature);
 
 void CYFinalize(JSObjectRef object);
 
index 580660e87026b829f1cee635b49e726bf33a4cf1..b3dcc0ae6fda6e724658a34350796a15649b3264 100644 (file)
@@ -389,7 +389,7 @@ struct Message_privateData :
     SEL sel_;
 
     Message_privateData(SEL sel, const char *type, IMP value = NULL) :
-        cy::Functor(type, reinterpret_cast<void (*)()>(value)),
+        cy::Functor(reinterpret_cast<void (*)()>(value), type),
         sel_(sel)
     {
     }
@@ -848,28 +848,24 @@ NSObject *CYCopyNSObject(CYPool &pool, JSContextRef context, JSValueRef value) {
 @end
 
 static const char *CYBlockEncoding(NSBlock *self);
-static sig::Signature *CYBlockSignature(CYPool &pool, NSBlock *self);
+static bool CYBlockSignature(CYPool &pool, NSBlock *self, sig::Signature &signature);
 
 @implementation NSBlock (Cycript)
 
 - (NSString *) cy$toCYON:(bool)objective inSet:(std::set<void *> &)objects {
     CYLocalPool pool;
 
-    sig::Signature *signature(CYBlockSignature(pool, self));
-    // XXX: I am checking signature->count due to Decode doing it for block_P
-    if (signature == NULL || signature->count == 0)
+    sig::Block type;
+    if (!CYBlockSignature(pool, self, type.signature))
         return [super cy$toCYON:objective inSet:objects];
     _oassert(objects.insert(self).second);
 
-    sig::Block type;
-    sig::Copy(pool, type.signature, *signature);
-
     CYTypedIdentifier *typed((new(pool) CYTypeExpression(CYDecodeType(pool, &type)))->typed_);
-    CYTypeFunctionWith *function(typed->Function());
-    _assert(function != NULL);
-
-    _assert(function->parameters_ != NULL);
-    CYObjCBlock *block(new(pool) CYObjCBlock(typed, function->parameters_, NULL));
+    CYTypeModifier *&modifier(CYGetLast(typed->modifier_));
+    CYTypeBlockWith *with(dynamic_cast<CYTypeBlockWith *>(modifier));
+    _assert(with != NULL);
+    CYObjCBlock *block(new(pool) CYObjCBlock(typed, with->parameters_, NULL));
+    modifier = NULL;
 
     std::ostringstream str;
     CYOptions options;
@@ -1932,14 +1928,21 @@ static const char *CYBlockEncoding(NSBlock *self) {
     return descriptor3->signature;
 }
 
-static sig::Signature *CYBlockSignature(CYPool &pool, NSBlock *self) {
+static bool CYBlockSignature(CYPool &pool, NSBlock *self, sig::Signature &signature) {
     const char *encoding(CYBlockEncoding(self));
     if (encoding == NULL)
-        return NULL;
-    // XXX: this should be stored on a FunctionInstance private value subclass
-    sig::Signature *signature(new(pool) sig::Signature());
-    sig::Parse(pool, signature, encoding, &Structor_);
-    return signature;
+        return false;
+
+    sig::Parse(pool, &signature, encoding, &Structor_);
+    _assert(signature.count >= 2);
+
+    _assert(dynamic_cast<sig::Object *>(signature.elements[1].type) != NULL);
+    signature.elements[1] = signature.elements[0];
+
+    ++signature.elements;
+    --signature.count;
+
+    return true;
 }
 
 static JSValueRef FunctionInstance_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1956,11 +1959,11 @@ static JSValueRef FunctionInstance_callAsFunction(JSContextRef context, JSObject
         sig::Parse(pool, &signature, encoding, &Structor_);
 
         ffi_cif cif;
-        sig::sig_ffi_cif(pool, &signature, &cif);
+        sig::sig_ffi_cif(pool, 0, signature, &cif);
 
         BlockLiteral *literal(reinterpret_cast<BlockLiteral *>(self));
         void (*function)() = reinterpret_cast<void (*)()>(literal->invoke);
-        return CYCallFunction(pool, context, 1, setup, count, arguments, false, &signature, &cif, function);
+        return CYCallFunction(pool, context, 1, setup, count, arguments, false, false, signature, &cif, function);
     }
 
     if (count != 0)
@@ -2409,24 +2412,8 @@ JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class _cla
     sig::Signature signature;
     sig::Parse(pool, &signature, type, &Structor_);
 
-    size_t used(count + 3);
-    if (used > signature.count) {
-        sig::Element *elements(new (pool) sig::Element[used]);
-        memcpy(elements, signature.elements, used * sizeof(sig::Element));
-
-        for (size_t index(signature.count); index != used; ++index) {
-            sig::Element *element(&elements[index]);
-            element->name = NULL;
-            element->offset = _not(size_t);
-            element->type = new(pool) sig::Object();
-        }
-
-        signature.elements = elements;
-        signature.count = used;
-    }
-
     ffi_cif cif;
-    sig::sig_ffi_cif(pool, &signature, &cif);
+    sig::sig_ffi_cif(pool, 0, signature, &cif);
 
     if (imp == NULL) {
 #ifndef CY_NO_STRET
@@ -2438,7 +2425,7 @@ JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class _cla
     }
 
     void (*function)() = reinterpret_cast<void (*)()>(imp);
-    return CYCallFunction(pool, context, 2, setup, count, arguments, initialize, &signature, &cif, function);
+    return CYCallFunction(pool, context, 2, setup, count, arguments, initialize, true, signature, &cif, function);
 }
 
 static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[]) {
@@ -2502,7 +2489,7 @@ static JSValueRef Message_callAsFunction(JSContextRef context, JSObjectRef objec
     setup[0] = &self;
     setup[1] = &internal->sel_;
 
-    return CYCallFunction(pool, context, 2, setup, count, arguments, false, &internal->signature_, &internal->cif_, internal->GetValue());
+    return CYCallFunction(pool, context, 2, setup, count, arguments, false, true, internal->signature_, &internal->cif_, internal->GetValue());
 } CYCatch(NULL) }
 
 static JSObjectRef Super_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -2553,13 +2540,25 @@ static JSValueRef CYValue_callAsFunction_$cya(JSContextRef context, JSObjectRef
     return CYMakePointer(context, &internal->value_, *type, ffi, object);
 } CYCatch(NULL) }
 
-static JSValueRef FunctionInstance_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+static JSValueRef Selector_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+    return CYMakeType(context, sig::Selector());
+} CYCatch(NULL) }
+
+static JSValueRef Instance_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+    return CYMakeType(context, sig::Object());
+} CYCatch(NULL) }
+
+static JSValueRef FunctionInstance_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     Instance *internal(reinterpret_cast<Instance *>(JSObjectGetPrivate(object)));
     CYPool pool;
-    sig::Signature *signature(CYBlockSignature(pool, internal->GetValue()));
-    if (signature == NULL)
+    sig::Block type;
+    if (!CYBlockSignature(pool, internal->GetValue(), type.signature))
         return CYJSNull(context);
-    return CYMakeType(context, signature);
+    return CYMakeType(context, type);
+} CYCatch(NULL) }
+
+static JSValueRef Class_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
+    return CYMakeType(context, sig::Meta());
 } CYCatch(NULL) }
 
 static JSValueRef Instance_getProperty_constructor(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
@@ -2700,18 +2699,20 @@ static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef
     objc_method *method(_require(class_getInstanceMethod(_class, sel)));
     const char *encoding(method_getTypeEncoding(method));
 
-    sig::Signature signature;
-    sig::Parse(pool, &signature, encoding, &Structor_);
-    return CYMakeType(context, &signature);
+    sig::Function type(false);
+    sig::Parse(pool, &type.signature, encoding, &Structor_);
+    return CYMakeType(context, type);
 } CYCatch(NULL) }
 
-static JSStaticValue Selector_staticValues[2] = {
+static JSStaticValue Selector_staticValues[3] = {
+    {"$cyt", &Selector_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"value", &CYValue_getProperty_value, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete},
     {NULL, NULL, NULL, 0}
 };
 
-// XXX: this is sadly duplicated in FunctionInstance_staticValues
-static JSStaticValue Instance_staticValues[5] = {
+static JSStaticValue Instance_staticValues[6] = {
+    {"$cyt", &Instance_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    // XXX: this is sadly duplicated in FunctionInstance_staticValues
     {"constructor", &Instance_getProperty_constructor, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"messages", &Instance_getProperty_messages, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"prototype", &Instance_getProperty_prototype, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
@@ -2720,7 +2721,7 @@ static JSStaticValue Instance_staticValues[5] = {
 };
 
 static JSStaticValue FunctionInstance_staticValues[6] = {
-    {"type", &FunctionInstance_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"$cyt", &FunctionInstance_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     // XXX: this is sadly a duplicate of Instance_staticValues
     {"constructor", &Instance_getProperty_constructor, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"messages", &Instance_getProperty_messages, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
@@ -2744,6 +2745,11 @@ static JSStaticFunction Class_staticFunctions[2] = {
     {NULL, NULL, 0}
 };
 
+static JSStaticValue Class_staticValues[2] = {
+    {"$cyt", &Class_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {NULL, NULL, NULL, 0}
+};
+
 static JSStaticFunction Internal_staticFunctions[2] = {
     {"$cya", &Internal_callAsFunction_$cya, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {NULL, NULL, 0}
@@ -2831,6 +2837,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry {
     definition = kJSClassDefinitionEmpty;
     definition.className = "Class";
     definition.staticFunctions = Class_staticFunctions;
+    definition.staticValues = Class_staticValues;
     Class_ = JSClassCreate(&definition);
 
     definition = kJSClassDefinitionEmpty;
index e4b073214b060ef03cb581318eebdc1d3f962f3b..89693574e3c3cc121797acf39c35ae66bbafc719 100644 (file)
@@ -177,7 +177,8 @@ struct CYMessageParameter :
     CYWord *name_;
     CYTypedIdentifier *type_;
 
-    CYMessageParameter(CYWord *name, CYTypedIdentifier *type) :
+    CYMessageParameter(CYWord *name, CYTypedIdentifier *type, CYMessageParameter *next = NULL) :
+        CYNext<CYMessageParameter>(next),
         name_(name),
         type_(type)
     {
index dc5782a2491af1fc0989e59eeef9cd3456a756e5..a6174087c8ddfbe67130c2e0ef3b8fc548d1bedf 100644 (file)
@@ -677,7 +677,13 @@ void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
 
 void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
     next_->Output(out, Precedence(), identifier);
-    out << '(' << parameters_ << ')';
+    out << '(' << parameters_;
+    if (variadic_) {
+        if (parameters_ != NULL)
+            out << ',' << ' ';
+        out << "...";
+    }
+    out << ')';
 }
 
 void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
index acda20a719a51fdbd1d724d57d2d0647d986c3e8..ec17e71153350d4d0c8d036e998636dff55920c4 100644 (file)
@@ -85,6 +85,7 @@
 %union { CYTypeStructField *structField_; }
 %union { CYTypeModifier *modifier_; }
 %union { CYTypeSpecifier *specifier_; }
+%union { CYTypedFormal *typedFormal_; }
 %union { CYTypedIdentifier *typedIdentifier_; }
 %union { CYTypedParameter *typedParameter_; }
 @end
@@ -434,6 +435,7 @@ type; })
 %token _synchronized_ "synchronized"
 %token _throws_ "throws"
 %token _transient_ "transient"
+%token _typeid_ "typeid"
 %token _volatile_ "volatile"
 %token _yield_ "yield"
 %token _yield__ "!yield"
@@ -677,9 +679,10 @@ type; })
 %type <typedIdentifier_> TypedIdentifierMaybe
 %type <typedIdentifier_> TypedIdentifierNo
 %type <typedIdentifier_> TypedIdentifierYes
-%type <typedParameter_> TypedParameterList_
-%type <typedParameter_> TypedParameterList
-%type <typedParameter_> TypedParameterListOpt
+%type <typedFormal_> TypedParameterList_
+%type <typedFormal_> TypedParameterList
+%type <typedFormal_> TypedParameterListOpt
+%type <typedParameter_> TypedParameters
 @end
 
 @begin ObjectiveC
@@ -972,6 +975,7 @@ IdentifierTypeNoOf
     | "target" { $$ = CYNew CYIdentifier("target"); }
     | "throws" { $$ = CYNew CYIdentifier("throws"); }
     | "transient" { $$ = CYNew CYIdentifier("transient"); }
+    | "typeid" { $$ = CYNew CYIdentifier("typeid"); }
     | "undefined" { $$ = CYNew CYIdentifier("undefined"); }
 @begin ObjectiveC
     | "bool" { $$ = CYNew CYIdentifier("bool"); }
@@ -2026,12 +2030,12 @@ ParameterModifierOpt
     ;
 
 ParameterTail
-    : TypedParameterListOpt[parameters] ")" ParameterModifierOpt { $$ = CYNew CYTypeFunctionWith($parameters); }
+    : TypedParameterListOpt[formal] ")" ParameterModifierOpt { $$ = CYNew CYTypeFunctionWith($formal->variadic_, $formal->parameters_); }
     ;
 
 SuffixedType
     : SuffixedTypeOpt[typed] "[" RestrictOpt NumericLiteral[size] "]" { $$ = $typed; $$->modifier_ = CYNew CYTypeArrayOf($size, $$->modifier_); }
-    | "(" "^" TypeQualifierRightOpt[typed] ")" "(" TypedParameterListOpt[parameters] ")" { $$ = $typed; $$->modifier_ = CYNew CYTypeBlockWith($parameters, $$->modifier_); }
+    | "(" "^" TypeQualifierRightOpt[typed] ")" "(" TypedParameters[parameters] ")" { $$ = $typed; $$->modifier_ = CYNew CYTypeBlockWith($parameters, $$->modifier_); }
     | TypeSignifier[typed] "(" ParameterTail[modifier] { $$ = $typed; CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; }
     | "("[parenthesis] ParameterTail[modifier] { $$ = CYNew CYTypedIdentifier(@parenthesis); CYSetLast($modifier) = $$->modifier_; $$->modifier_ = $modifier; }
     ;
@@ -2163,7 +2167,7 @@ MessageParameterList
 
 MessageParameterListOpt
     : MessageParameterList[pass] { $$ = $pass; }
-    | { $$ = NULL; }
+    | TypedParameterList_[formal] { if ($formal->variadic_) CYERR(@$, "unsupported variadic"); /*XXX*/ if ($formal->parameters_ != NULL) CYERR(@$, "temporarily unsupported"); $$ = NULL; }
     ;
 
 MessageParameters
@@ -2346,21 +2350,26 @@ MemberAccess
 /* Cycript (C): Lambda Expressions {{{ */
 TypedParameterList_
     : "," TypedParameterList[parameters] { $$ = $parameters; }
-    | { $$ = NULL; }
+    | { $$ = CYNew CYTypedFormal(false); }
     ;
 
 TypedParameterList
-    : TypedIdentifierMaybe[typed] TypedParameterList_[next] { $$ = CYNew CYTypedParameter($typed, $next); }
+    : TypedIdentifierMaybe[typed] TypedParameterList_[formal] { $$ = $formal; $$->parameters_ = CYNew CYTypedParameter($typed, $$->parameters_); }
+    | "..." { $$ = CYNew CYTypedFormal(true); }
     ;
 
 TypedParameterListOpt
     : TypedParameterList[pass] { $$ = $pass; }
-    | "void" { $$ = NULL; }
-    | { $$ = NULL; }
+    | "void" { $$ = CYNew CYTypedFormal(false); }
+    | { $$ = CYNew CYTypedFormal(false); }
+    ;
+
+TypedParameters
+    : TypedParameterListOpt[formal] { if ($formal->variadic_) CYERR(@$, "unsupported variadic"); $$ = $formal->parameters_; }
     ;
 
 PrimaryExpression
-    : "[" LexOf "&" "]" "(" TypedParameterListOpt[parameters] ")" "->" TypedIdentifierNo[type] "{" FunctionBody[code] "}" { $$ = CYNew CYLambda($type, $parameters, $code); }
+    : "[" LexOf "&" "]" "(" TypedParameters[parameters] ")" "->" TypedIdentifierNo[type] "{" FunctionBody[code] "}" { $$ = CYNew CYLambda($type, $parameters, $code); }
     ;
 /* }}} */
 /* Cycript (C): Structure Definitions {{{ */
index ca05d082395cb5f79a4079f27946e1349cb20bfb..719b3a57eeca3a67f7663d976cadf874d802fec0 100644 (file)
@@ -1233,7 +1233,10 @@ CYTarget *CYTypeModifier::Replace(CYContext &context, CYTarget *type) { $T(type)
 }
 
 CYTarget *CYTypeFunctionWith::Replace_(CYContext &context, CYTarget *type) {
-    return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("functionWith")), parameters_->Argument(context)));
+    CYList<CYArgument> arguments(parameters_->Argument(context));
+    if (variadic_)
+        arguments->*$C_($ CYNull());
+    return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("functionWith")), arguments));
 }
 
 CYTarget *CYTypePointerTo::Replace_(CYContext &context, CYTarget *type) {
@@ -1268,15 +1271,15 @@ CYTarget *CYTypedIdentifier::Replace(CYContext &context) {
 }
 
 CYTypeFunctionWith *CYTypedIdentifier::Function() {
-    CYTypeModifier **modifier(&modifier_);
-    if (*modifier == NULL)
+    CYTypeModifier *&modifier(CYGetLast(modifier_));
+    if (modifier == NULL)
         return NULL;
-    while ((*modifier)->next_ != NULL)
-        modifier = &(*modifier)->next_;
-    CYTypeFunctionWith *function((*modifier)->Function());
+
+    CYTypeFunctionWith *function(modifier->Function());
     if (function == NULL)
         return NULL;
-    *modifier = NULL;
+
+    modifier = NULL;
     return function;
 }
 
index 7df83885fd9e822c1d81770e0915f9088552c0ea..edadb8f9a6f640292a4932223461d0bcb419551a 100644 (file)
@@ -510,6 +510,7 @@ XMLName {XMLNameStart}{XMLNamePart}*
 "transient"       L /*FII*/ F(tk::_transient_, hi::Meta);
 "true"            L /*LLL*/ F(tk::_true_, hi::Constant);
 "try"             L /*KKK*/ F(tk::_try_, hi::Control);
+"typeid"          L /*III*/ F(tk::_typeid_, hi::Operator);
 "typeof"          L /*KKK*/ F(tk::_typeof_, hi::Operator);
 "var"             L /*KKK*/ F(tk::_var_, hi::Meta);
 "void"            L /*KKK*/ F(tk::_void_, hi::Operator);
index 9786ee7be23ed1ed21bd3f9ba7a1928db4a1e51f..abf05bcc31933717419330ba8917b1acb8caa912 100644 (file)
@@ -2226,6 +2226,17 @@ struct CYTypedParameter :
     virtual void Output(CYOutput &out) const;
 };
 
+struct CYTypedFormal {
+    bool variadic_;
+    CYTypedParameter *parameters_;
+
+    CYTypedFormal(bool variadic) :
+        variadic_(variadic),
+        parameters_(NULL)
+    {
+    }
+};
+
 struct CYLambda :
     CYTarget
 {
@@ -2381,10 +2392,12 @@ struct CYTypeBlockWith :
 struct CYTypeFunctionWith :
     CYTypeModifier
 {
+    bool variadic_;
     CYTypedParameter *parameters_;
 
-    CYTypeFunctionWith(CYTypedParameter *parameters, CYTypeModifier *next = NULL) :
+    CYTypeFunctionWith(bool variadic, CYTypedParameter *parameters, CYTypeModifier *next = NULL) :
         CYTypeModifier(next),
+        variadic_(variadic),
         parameters_(parameters)
     {
     }
index 46d3410507488340e76a26e838b0f700bdfc318e..2286294472f484d68f974e4a3ea05198688e8b99 100644 (file)
@@ -12,6 +12,9 @@
 /* Define to 1 if you have the <ffi.h> header file. */
 #undef HAVE_FFI_H
 
+/* Define to 1 if you have the `ffi_prep_cif_var' function. */
+#undef HAVE_FFI_PREP_CIF_VAR
+
 /* Define to 1 if you have the `Foundation' framework (-framework Foundation).
    */
 #undef HAVE_FRAMEWORK_FOUNDATION
index 0dfc278020b6268904fd2d9a443c0d8df3556fec..3cb5c3cece342d0bb3163cf79babc20e3d1f07b9 100755 (executable)
--- a/configure
+++ b/configure
@@ -1557,6 +1557,9 @@ Some influential environment variables:
   WEBKIT_CFLAGS
               C compiler flags for WEBKIT, overriding pkg-config
   WEBKIT_LIBS linker flags for WEBKIT, overriding pkg-config
+  LIBFFI_CFLAGS
+              C compiler flags for LIBFFI, overriding pkg-config
+  LIBFFI_LIBS linker flags for LIBFFI, overriding pkg-config
   GNUSTEP_CONFIG
               prints information about the current gnustep installation
 
@@ -2154,6 +2157,73 @@ fi
 
 } # ac_fn_cxx_check_header_mongrel
 
+# ac_fn_cxx_check_func LINENO FUNC VAR
+# ------------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_cxx_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_func
+
 # ac_fn_objcxx_try_link LINENO
 # ----------------------------
 # Try to link conftest.$ac_ext, and return whether this succeeded.
@@ -22644,9 +22714,6 @@ done
     if test "x$ac_cv_header_ffi_h" = xno && test "x$ac_cv_header_ffi_ffi_h" = xno; then :
 
 
-      LIBFFI_CFLAGS
-              C compiler flags for LIBFFI, overriding pkg-config
-  LIBFFI_LIBS linker flags for LIBFFI, overriding pkg-config
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBFFI" >&5
@@ -22948,6 +23015,17 @@ fi ;; #(
   *) :
      ;;
 esac
+        for ac_func in ffi_prep_cif_var
+do :
+  ac_fn_cxx_check_func "$LINENO" "ffi_prep_cif_var" "ac_cv_func_ffi_prep_cif_var"
+if test "x$ac_cv_func_ffi_prep_cif_var" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_FFI_PREP_CIF_VAR 1
+_ACEOF
+
+fi
+done
+
 
 fi
     LTLIBFFI=$LIBS
index a1c34d3cf28d361989ce82d9069939eb9de95c15..aee07a593e74ad0852ff0f50cc1c8f7e35d7e2eb 100644 (file)
@@ -211,12 +211,13 @@ AS_CASE([$CY_EXECUTE], [1], [
 
     AC_CHECK_HEADERS([ffi.h ffi/ffi.h], [break])
 
-    CY_LT_LIB([LTLIBFFI], AS_IF([test "x$ac_cv_header_ffi_h" = xno && test "x$ac_cv_header_ffi_ffi_h" = xno], [
+    CY_LT_LIB([LTLIBFFI], [AS_IF([test "x$ac_cv_header_ffi_h" = xno && test "x$ac_cv_header_ffi_ffi_h" = xno], [
         CY_CHECK_PKG_CONFIG_LIBFFI
     ], [
         AC_SEARCH_LIBS([ffi_call], [ffi])
         AS_CASE([$ac_cv_search_ffi_call], [no], [CY_CHECK_PKG_CONFIG_LIBFFI])
-    ]))
+        AC_CHECK_FUNCS([ffi_prep_cif_var])
+    ])])
 
     AC_CHECK_FRAMEWORK([JavaVM], [
         #include <JavaVM/jni.h>
index 8640a7490e7bc83e3d4c5629d9a5be2bcd56b9f6..4014fd6a06f9a5c01908c64c105c60d60bdb682c 100644 (file)
@@ -25,6 +25,10 @@ var process = {
 
 (function() {
 
+this.typeid = function(object) {
+    return object.$cyt;
+};
+
 let $cy_set = function(object, properties) {
     for (const name in properties)
         Object.defineProperty(object, name, {
@@ -67,6 +71,8 @@ $cy_set(Error.prototype, {
 
 $cy_set(Number.prototype, {
     toCYON: function() {
+        if ("$cyt" in this)
+            return `${this.$cyt.toCYON()}(${this.toString()})`;
         return `new Number(${this.toString()})`;
     },
 });
index 2cd98b8eb6f9009125294193b358760dbad69303..446b906bf560c50861985d6d89e22c95e0ed177e 100644 (file)
@@ -61,7 +61,7 @@ exports.getImageByName = MSGetImageByName;
 exports.findSymbol = MSFindSymbol;
 
 exports.hookFunction = function(func, hook, old) {
-    var type = func.type;
+    var type = typeid(func);
 
     var pointer;
     if (old == null || typeof old === "undefined")
index 8b43fc1187664a17162010b45b41b7621f3864a6..4fb98bdd1ce056f50168411eb0c171b4c965a2b4 100644 (file)
@@ -91,7 +91,7 @@ Aggregate *Aggregate::Copy(CYPool &pool, const char *name) const {
 }
 
 Function *Function::Copy(CYPool &pool, const char *name) const {
-    Function *copy(new(pool) Function());
+    Function *copy(new(pool) Function(variadic));
     sig::Copy(pool, copy->signature, signature);
     return copy;
 }
index 73b3912dcc10038cb473dd30357f25f5c89c2df2..e114db876e18f21abac0a377ec04b1a7313c8574 100644 (file)
 
 namespace sig {
 
-void sig_ffi_types(
-    CYPool &pool,
-    const struct Signature *signature,
-    ffi_type **types,
-    size_t skip = 0,
-    size_t offset = 0
-) {
-    _assert(signature->count >= skip);
-    for (size_t index = skip; index != signature->count; ++index)
-        types[index - skip + offset] = signature->elements[index].type->GetFFI(pool);
-}
-
 template <>
 ffi_type *Primitive<bool>::GetFFI(CYPool &pool) const {
     return &ffi_type_uchar;
@@ -171,7 +159,8 @@ ffi_type *Aggregate::GetFFI(CYPool &pool) const {
     ffi->type = FFI_TYPE_STRUCT;
 
     ffi->elements = new(pool) ffi_type *[signature.count + 1];
-    sig_ffi_types(pool, &signature, ffi->elements);
+    for (size_t index(0); index != signature.count; ++index)
+        ffi->elements[index] = signature.elements[index].type->GetFFI(pool);
     ffi->elements[signature.count] = NULL;
 
     return ffi;
@@ -185,19 +174,24 @@ ffi_type *Block::GetFFI(CYPool &pool) const {
     return &ffi_type_pointer;
 }
 
-void sig_ffi_cif(
-    CYPool &pool,
-    struct Signature *signature,
-    ffi_cif *cif,
-    size_t skip,
-    ffi_type **types,
-    size_t offset
-) {
-    if (types == NULL)
-        types = new(pool) ffi_type *[signature->count - 1];
-    ffi_type *type = signature->elements[0].type->GetFFI(pool);
-    sig_ffi_types(pool, signature, types, 1 + skip, offset);
-    ffi_status status = ffi_prep_cif(cif, FFI_DEFAULT_ABI, signature->count - 1 - skip + offset, type, types);
+void sig_ffi_cif(CYPool &pool, size_t variadic, const Signature &signature, ffi_cif *cif) {
+    _assert(signature.count != 0);
+    size_t count(signature.count - 1);
+    ffi_type *type(signature.elements[0].type->GetFFI(pool));
+
+    ffi_type **types(new(pool) ffi_type *[count]);
+    for (size_t index(0); index != count; ++index)
+        types[index] = signature.elements[index + 1].type->GetFFI(pool);
+
+    ffi_status status;
+#ifdef HAVE_FFI_PREP_CIF_VAR
+    if (variadic == 0)
+#endif
+        status = ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, type, types);
+#ifdef HAVE_FFI_PREP_CIF_VAR
+    else
+        status = ffi_prep_cif_var(cif, FFI_DEFAULT_ABI, variadic - 1, count, type, types);
+#endif
     _assert(status == FFI_OK);
 }
 
index b654e0f776cea6af9ccc1ea1bcbd0f1600038049..29442976069b995048446275fff0a83fab331965 100644 (file)
 
 namespace sig {
 
-void sig_ffi_cif(
-    CYPool &pool,
-    struct Signature *signature,
-    ffi_cif *cif,
-    size_t skip = 0,
-    ffi_type **types = NULL,
-    size_t offset = 0
-);
+void sig_ffi_cif(CYPool &pool, size_t variadic, const Signature &signature, ffi_cif *cif);
 
 void Copy(CYPool &pool, ffi_type &lhs, ffi_type &rhs);
 
index 3bed8fd0ca5b8447adbe0c0143b106182388f050..f0530466c8a01d5c4e364cc36bdfb286a282daf7 100644 (file)
@@ -37,6 +37,7 @@
 
 class CYPool;
 struct CYTypedIdentifier;
+struct CYTypedParameter;
 
 namespace sig {
 
@@ -270,15 +271,25 @@ struct Callable :
     Type
 {
     Signature signature;
+
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+    virtual CYTypedIdentifier *Modify(CYPool &pool, CYTypedIdentifier *result, CYTypedParameter *parameters) const = 0;
 };
 
 struct Function :
     Callable
 {
+    bool variadic;
+
+    Function(bool variadic) :
+        variadic(variadic)
+    {
+    }
+
     Function *Copy(CYPool &pool, const char *name = NULL) const override;
 
     const char *Encode(CYPool &pool) const override;
-    CYTypedIdentifier *Decode(CYPool &pool) const override;
+    CYTypedIdentifier *Modify(CYPool &pool, CYTypedIdentifier *result, CYTypedParameter *parameters) const override;
 
     ffi_type *GetFFI(CYPool &pool) const override;
     void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
@@ -292,6 +303,7 @@ struct Block :
 
     const char *Encode(CYPool &pool) const override;
     CYTypedIdentifier *Decode(CYPool &pool) const override;
+    CYTypedIdentifier *Modify(CYPool &pool, CYTypedIdentifier *result, CYTypedParameter *parameters) const override;
 
     ffi_type *GetFFI(CYPool &pool) const override;
     void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;