]> git.saurik.com Git - cycript.git/commitdiff
Replace sig::Primitive with full object hierarchy.
authorJay Freeman (saurik) <saurik@saurik.com>
Tue, 29 Dec 2015 16:03:49 +0000 (08:03 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Tue, 29 Dec 2015 16:03:49 +0000 (08:03 -0800)
16 files changed:
Decode.cpp
Decode.hpp
Execute.cpp
Internal.hpp
JavaScript.hpp
ObjectiveC/Library.mm
Output.cpp
Parser.ypp.in
Replace.cpp
Syntax.hpp
sig/copy.cpp
sig/ffi_type.cpp
sig/ffi_type.hpp
sig/parse.cpp
sig/parse.hpp
sig/types.hpp

index acf8b957dacb517f6fb0cf3f3cd7d19de6ebea35..2187f268c32dc230f01e2bbb9eea0296f1157036 100644 (file)
 #include "Decode.hpp"
 #include "Replace.hpp"
 
-CYTypedIdentifier *Decode_(CYPool &pool, struct sig::Type *type) {
-    switch (type->primitive) {
-        case sig::unknown_P: return $ CYTypedIdentifier($ CYTypeError());
-
-        case sig::function_P: {
-            _assert(type->data.signature.count != 0);
-            CYTypedParameter *parameter(NULL);
-            for (size_t i(type->data.signature.count - 1); i != 0; --i)
-                parameter = $ CYTypedParameter(Decode(pool, type->data.signature.elements[i].type), parameter);
-            return Decode(pool, type->data.signature.elements[0].type)->Modify($ CYTypeFunctionWith(parameter));
-        } break;
-
-        case sig::typename_P: return $ CYTypedIdentifier($ CYTypeVariable("Class"));
-        case sig::union_P: _assert(false); break;
-        case sig::string_P: return $ CYTypedIdentifier($ CYTypeVariable("char"), $ CYTypePointerTo());
-        case sig::selector_P: return $ CYTypedIdentifier($ CYTypeVariable("SEL"));
-
-        case sig::block_P: {
-            if (type->data.signature.count == 0)
-                return $ CYTypedIdentifier($ CYTypeVariable("NSBlock"), $ CYTypePointerTo());
-            else {
-                CYTypedParameter *parameter(NULL);
-                for (size_t i(type->data.signature.count - 1); i != 0; --i)
-                    parameter = $ CYTypedParameter(Decode(pool, type->data.signature.elements[i].type), parameter);
-                return Decode(pool, type->data.signature.elements[0].type)->Modify($ CYTypeBlockWith(parameter));
-            }
-        } break;
-
-        case sig::object_P: {
-            if (type->name == NULL)
-                return $ CYTypedIdentifier($ CYTypeVariable("id"));
-            else
-                return $ CYTypedIdentifier($ CYTypeVariable(type->name), $ CYTypePointerTo());
-        } break;
-
-        case sig::boolean_P: return $ CYTypedIdentifier($ CYTypeVariable("bool"));
-        case sig::uchar_P: return $ CYTypedIdentifier($ CYTypeUnsigned($ CYTypeVariable("char")));
-        case sig::uint_P: return $ CYTypedIdentifier($ CYTypeUnsigned($ CYTypeVariable("int")));
-        case sig::ulong_P: return $ CYTypedIdentifier($ CYTypeUnsigned($ CYTypeLong($ CYTypeVariable("int"))));
-        case sig::ulonglong_P: return $ CYTypedIdentifier($ CYTypeUnsigned($ CYTypeLong($ CYTypeLong($ CYTypeVariable("int")))));
-        case sig::ushort_P: return $ CYTypedIdentifier($ CYTypeUnsigned($ CYTypeShort($ CYTypeVariable("int"))));
-        case sig::array_P: return Decode(pool, type->data.data.type)->Modify($ CYTypeArrayOf($D(type->data.data.size)));
-
-        case sig::pointer_P: {
-            CYTypedIdentifier *typed;
-            if (type->data.data.type == NULL)
-                typed = $ CYTypedIdentifier($ CYTypeVoid());
-            else
-                typed = Decode(pool, type->data.data.type);
-            return typed->Modify($ CYTypePointerTo());
-        } break;
-
-        case sig::bit_P: _assert(false); break;
-        case sig::schar_P: return $ CYTypedIdentifier($ CYTypeSigned($ CYTypeVariable("char")));
-        case sig::double_P: return $ CYTypedIdentifier($ CYTypeVariable("double"));
-        case sig::float_P: return $ CYTypedIdentifier($ CYTypeVariable("float"));
-        case sig::int_P: return $ CYTypedIdentifier($ CYTypeVariable("int"));
-        case sig::long_P: return $ CYTypedIdentifier($ CYTypeLong($ CYTypeVariable("int")));
-        case sig::longlong_P: return $ CYTypedIdentifier($ CYTypeLong($ CYTypeLong($ CYTypeVariable("int"))));
-        case sig::short_P: return $ CYTypedIdentifier($ CYTypeShort($ CYTypeVariable("int")));
-
-        case sig::void_P: return $ CYTypedIdentifier($ CYTypeVoid());
-        case sig::char_P: return $ CYTypedIdentifier($ CYTypeVariable("char"));
-
-        case sig::struct_P: {
-            CYTypeStructField *fields(NULL);
-            for (size_t i(type->data.signature.count); i != 0; --i) {
-                sig::Element &element(type->data.signature.elements[i - 1]);
-                CYTypedIdentifier *typed(Decode(pool, element.type));
-                if (element.name != NULL)
-                    typed->identifier_ = $I(element.name);
-                fields = $ CYTypeStructField(typed, fields);
-            }
-            CYIdentifier *name(type->name == NULL ? NULL : $I(type->name));
-            return $ CYTypedIdentifier($ CYTypeStruct(name, $ CYStructTail(fields)));
-        } break;
-    }
+namespace sig {
+
+template <>
+CYTypedIdentifier *Primitive<bool>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeVariable("bool"));
+}
+
+template <>
+CYTypedIdentifier *Primitive<char>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeCharacter(CYTypeNeutral));
+}
+
+template <>
+CYTypedIdentifier *Primitive<double>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeVariable("double"));
+}
+
+template <>
+CYTypedIdentifier *Primitive<float>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeVariable("float"));
+}
+
+template <>
+CYTypedIdentifier *Primitive<signed char>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeCharacter(CYTypeSigned));
+}
+
+template <>
+CYTypedIdentifier *Primitive<signed int>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeSigned, 1));
+}
+
+template <>
+CYTypedIdentifier *Primitive<signed long int>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeSigned, 2));
+}
+
+template <>
+CYTypedIdentifier *Primitive<signed long long int>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeSigned, 3));
+}
+
+template <>
+CYTypedIdentifier *Primitive<signed short int>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeSigned, 0));
+}
+
+template <>
+CYTypedIdentifier *Primitive<unsigned char>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeCharacter(CYTypeUnsigned));
+}
+
+template <>
+CYTypedIdentifier *Primitive<unsigned int>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeUnsigned, 1));
+}
+
+template <>
+CYTypedIdentifier *Primitive<unsigned long int>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeUnsigned, 2));
+}
+
+template <>
+CYTypedIdentifier *Primitive<unsigned long long int>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeUnsigned, 3));
+}
+
+template <>
+CYTypedIdentifier *Primitive<unsigned short int>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeUnsigned, 0));
+}
+
+CYTypedIdentifier *Void::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeVoid());
+}
+
+CYTypedIdentifier *Unknown::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeError());
+}
+
+CYTypedIdentifier *String::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeCharacter(CYTypeNeutral), $ CYTypePointerTo());
+}
 
+CYTypedIdentifier *Meta::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeVariable("Class"));
+}
+
+CYTypedIdentifier *Selector::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeVariable("SEL"));
+}
+
+CYTypedIdentifier *Bits::Decode(CYPool &pool) const {
     _assert(false);
-    return NULL;
 }
 
-CYTypedIdentifier *Decode(CYPool &pool, struct sig::Type *type) {
-    CYTypedIdentifier *typed(Decode_(pool, type));
+CYTypedIdentifier *Pointer::Decode(CYPool &pool) const {
+    return CYDecodeType(pool, &type)->Modify($ CYTypePointerTo());
+}
+
+CYTypedIdentifier *Array::Decode(CYPool &pool) const {
+    return CYDecodeType(pool, &type)->Modify($ CYTypeArrayOf($D(size)));
+}
+
+CYTypedIdentifier *Object::Decode(CYPool &pool) const {
+    if (name == NULL)
+        return $ CYTypedIdentifier($ CYTypeVariable("id"));
+    else
+        return $ CYTypedIdentifier($ CYTypeVariable(name), $ CYTypePointerTo());
+}
+
+CYTypedIdentifier *Aggregate::Decode(CYPool &pool) const {
+    _assert(!overlap);
+
+    CYTypeStructField *fields(NULL);
+    for (size_t i(signature.count); i != 0; --i) {
+        sig::Element &element(signature.elements[i - 1]);
+        CYTypedIdentifier *typed(CYDecodeType(pool, element.type));
+        if (element.name != NULL)
+            typed->identifier_ = $I(element.name);
+        fields = $ CYTypeStructField(typed, fields);
+    }
+    CYIdentifier *identifier(name == NULL ? NULL : $I(name));
+    return $ CYTypedIdentifier($ CYTypeStruct(identifier, $ CYStructTail(fields)));
+}
+
+CYTypedIdentifier *Function::Decode(CYPool &pool) const {
+    _assert(signature.count != 0);
+    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($ CYTypeFunctionWith(parameter));
+}
+
+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));
+    }
+}
+
+}
+
+CYTypedIdentifier *CYDecodeType(CYPool &pool, struct sig::Type *type) {
+    CYTypedIdentifier *typed(type->Decode(pool));
     if ((type->flags & JOC_TYPE_CONST) != 0) {
-        if (type->primitive == sig::string_P)
+        if (dynamic_cast<sig::String *>(type) != NULL)
             typed->modifier_ = $ CYTypeConstant(typed->modifier_);
         else
             typed = typed->Modify($ CYTypeConstant());
index be4e8b91dcb3b24b12e5686c1b32943d30669c03..24f95b4a5526767af5606995e288dba58608ffa2 100644 (file)
@@ -26,6 +26,6 @@
 
 #include "Syntax.hpp"
 
-CYTypedIdentifier *Decode(CYPool &pool, struct sig::Type *type);
+CYTypedIdentifier *CYDecodeType(CYPool &pool, struct sig::Type *type);
 
 #endif//DECODE_HPP
index 41ba5836b81d5af4b0f58a696131f931daa1b7d1..1624b29e4c3ffdf64d0395a5b8204d4dd1b8bf6a 100644 (file)
@@ -201,22 +201,9 @@ void CYFinalize(JSObjectRef object) {
         delete internal;
 }
 
-void Structor_(CYPool &pool, sig::Type *&type) {
-    if (
-        type->primitive == sig::pointer_P &&
-        type->data.data.type->primitive == sig::struct_P &&
-        type->data.data.type->name != NULL &&
-        strcmp(type->data.data.type->name, "_objc_class") == 0
-    ) {
-        type->primitive = sig::typename_P;
-        type->data.data.type = NULL;
-        return;
-    }
-
-    if (type->primitive != sig::struct_P || type->name == NULL)
-        return;
-
+sig::Type *Structor_(CYPool &pool, sig::Aggregate *aggregate) {
     //_assert(false);
+    return aggregate;
 }
 
 JSClassRef Type_privateData::Class_;
@@ -247,7 +234,7 @@ struct Pointer :
     Type_privateData *type_;
     size_t length_;
 
-    Pointer(void *value, JSContextRef context, JSObjectRef owner, size_t length, sig::Type *type) :
+    Pointer(void *value, JSContextRef context, JSObjectRef owner, size_t length, const sig::Type &type) :
         CYOwned(value, context, owner),
         type_(new(*pool_) Type_privateData(type)),
         length_(length)
@@ -273,7 +260,7 @@ struct Struct_privateData :
     }
 };
 
-JSObjectRef CYMakeStruct(JSContextRef context, void *data, sig::Type *type, ffi_type *ffi, JSObjectRef owner) {
+JSObjectRef CYMakeStruct(JSContextRef context, void *data, const sig::Type &type, ffi_type *ffi, JSObjectRef owner) {
     Struct_privateData *internal(new Struct_privateData(context, owner));
     CYPool &pool(*internal->pool_);
     Type_privateData *typical(new(pool) Type_privateData(type, ffi));
@@ -622,7 +609,7 @@ static JSValueRef String_callAsFunction_toCYON(JSContextRef context, JSObjectRef
     return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size())));
 } CYCatch(NULL) }
 
-JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, sig::Type *type, ffi_type *ffi, JSObjectRef owner) {
+JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, const sig::Type &type, ffi_type *ffi, JSObjectRef owner) {
     Pointer *internal(new Pointer(pointer, context, owner, length, type));
     return JSObjectMake(context, Pointer_, internal);
 }
@@ -689,162 +676,173 @@ void *CYCastPointer_(JSContextRef context, JSValueRef value, bool *guess) {
     }
 }
 
-void CYPoolFFI(CYPool *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value) {
-    switch (type->primitive) {
-        case sig::boolean_P:
-            *reinterpret_cast<bool *>(data) = JSValueToBoolean(context, value);
-        break;
-
-#define CYPoolFFI_(primitive, native) \
-        case sig::primitive ## _P: \
-            *reinterpret_cast<native *>(data) = CYCastDouble(context, value); \
-        break;
-
-        CYPoolFFI_(uchar, unsigned char)
-        CYPoolFFI_(schar, signed char)
-        CYPoolFFI_(ushort, unsigned short)
-        CYPoolFFI_(short, short)
-        CYPoolFFI_(ulong, unsigned long)
-        CYPoolFFI_(long, long)
-        CYPoolFFI_(uint, unsigned int)
-        CYPoolFFI_(int, int)
-        CYPoolFFI_(ulonglong, unsigned long long)
-        CYPoolFFI_(longlong, long long)
-        CYPoolFFI_(float, float)
-        CYPoolFFI_(double, double)
-
-        case sig::array_P: {
-            uint8_t *base(reinterpret_cast<uint8_t *>(data));
-            JSObjectRef aggregate(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
-            for (size_t index(0); index != type->data.data.size; ++index) {
-                ffi_type *field(ffi->elements[index]);
-
-                JSValueRef rhs;
-                if (aggregate == NULL)
-                    rhs = value;
-                else {
-                    rhs = CYGetProperty(context, aggregate, index);
-                    if (JSValueIsUndefined(context, rhs))
-                        throw CYJSError(context, "unable to extract array value");
-                }
-
-                CYPoolFFI(pool, context, type->data.data.type, field, base, rhs);
-                // XXX: alignment?
-                base += field->size;
-            }
-        } break;
+namespace sig {
 
-        case sig::pointer_P:
-            *reinterpret_cast<void **>(data) = CYCastPointer<void *>(context, value);
-        break;
+// XXX: this is somehow not quite a template :/
 
-        case sig::string_P: {
-            bool guess(false);
-            *reinterpret_cast<const char **>(data) = CYCastPointer<const char *>(context, value, &guess);
-            if (guess && pool != NULL)
-                *reinterpret_cast<const char **>(data) = CYPoolCString(*pool, context, value);
-        } break;
+template <>
+void Primitive<bool>::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    *reinterpret_cast<bool *>(data) = JSValueToBoolean(context, value);
+}
 
-        case sig::struct_P: {
-            uint8_t *base(reinterpret_cast<uint8_t *>(data));
-            JSObjectRef aggregate(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
-            for (size_t index(0); index != type->data.signature.count; ++index) {
-                sig::Element *element(&type->data.signature.elements[index]);
-                ffi_type *field(ffi->elements[index]);
-
-                JSValueRef rhs;
-                if (aggregate == NULL)
-                    rhs = value;
-                else {
-                    rhs = CYGetProperty(context, aggregate, index);
-                    if (JSValueIsUndefined(context, rhs)) {
-                        if (element->name != NULL)
-                            rhs = CYGetProperty(context, aggregate, CYJSString(element->name));
-                        else
-                            goto undefined;
-                        if (JSValueIsUndefined(context, rhs)) undefined:
-                            throw CYJSError(context, "unable to extract structure value");
-                    }
-                }
-
-                CYPoolFFI(pool, context, element->type, field, base, rhs);
-                // XXX: alignment?
-                base += field->size;
-            }
-        } break;
+#define CYPoolFFI_(Type_) \
+template <> \
+void Primitive<Type_>::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const { \
+    *reinterpret_cast<Type_ *>(data) = CYCastDouble(context, value); \
+}
+
+CYPoolFFI_(char)
+CYPoolFFI_(double)
+CYPoolFFI_(float)
+CYPoolFFI_(signed char)
+CYPoolFFI_(signed int)
+CYPoolFFI_(signed long int)
+CYPoolFFI_(signed long long int)
+CYPoolFFI_(signed short int)
+CYPoolFFI_(unsigned char)
+CYPoolFFI_(unsigned int)
+CYPoolFFI_(unsigned long int)
+CYPoolFFI_(unsigned long long int)
+CYPoolFFI_(unsigned short int)
 
-        case sig::void_P:
-        break;
+void Void::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    _assert(false);
+}
 
-        // XXX: implement a conversion from a single character string?
-        CYPoolFFI_(char, char)
+void Unknown::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    _assert(false);
+}
 
-        default:
-            for (CYHook *hook : GetHooks())
-                if (hook->PoolFFI != NULL)
-                    if ((*hook->PoolFFI)(pool, context, type, ffi, data, value))
-                        return;
+void String::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    bool guess(false);
+    *reinterpret_cast<const char **>(data) = CYCastPointer<const char *>(context, value, &guess);
+    if (guess && pool != NULL)
+        *reinterpret_cast<const char **>(data) = CYPoolCString(*pool, context, value);
+}
 
-            CYThrow("unimplemented signature code: '%c''\n", type->primitive);
+void Bits::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    _assert(false);
+}
+
+void Pointer::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    *reinterpret_cast<void **>(data) = CYCastPointer<void *>(context, value);
+}
+
+void Array::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    uint8_t *base(reinterpret_cast<uint8_t *>(data));
+    JSObjectRef aggregate(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
+    for (size_t index(0); index != size; ++index) {
+        ffi_type *field(ffi->elements[index]);
+
+        JSValueRef rhs;
+        if (aggregate == NULL)
+            rhs = value;
+        else {
+            rhs = CYGetProperty(context, aggregate, index);
+            if (JSValueIsUndefined(context, rhs))
+                throw CYJSError(context, "unable to extract array value");
+        }
+
+        type.PoolFFI(pool, context, field, base, rhs);
+        // XXX: alignment?
+        base += field->size;
     }
 }
 
-JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) {
-    switch (type->primitive) {
-        case sig::boolean_P:
-            return CYCastJSValue(context, *reinterpret_cast<bool *>(data));
-
-#define CYFromFFI_(primitive, native) \
-        case sig::primitive ## _P: \
-            return CYCastJSValue(context, *reinterpret_cast<native *>(data)); \
-
-        CYFromFFI_(uchar, unsigned char)
-        CYFromFFI_(schar, signed char)
-        CYFromFFI_(ushort, unsigned short)
-        CYFromFFI_(short, short)
-        CYFromFFI_(ulong, unsigned long)
-        CYFromFFI_(long, long)
-        CYFromFFI_(uint, unsigned int)
-        CYFromFFI_(int, int)
-        CYFromFFI_(ulonglong, unsigned long long)
-        CYFromFFI_(longlong, long long)
-        CYFromFFI_(float, float)
-        CYFromFFI_(double, double)
-
-        case sig::array_P:
-            if (void *pointer = data)
-                return CYMakePointer(context, pointer, type->data.data.size, type->data.data.type, NULL, owner);
-            else goto null;
-
-        case sig::pointer_P:
-            if (void *pointer = *reinterpret_cast<void **>(data))
-                return CYMakePointer(context, pointer, _not(size_t), type->data.data.type, NULL, owner);
-            else goto null;
-
-        case sig::string_P:
-            if (char *pointer = *reinterpret_cast<char **>(data))
-                return CYMakeCString(context, pointer, owner);
-            else goto null;
-
-        case sig::struct_P:
-            return CYMakeStruct(context, data, type, ffi, owner);
-        case sig::void_P:
-            return CYJSUndefined(context);
-
-        CYFromFFI_(char, char)
-
-        null:
-            return CYJSNull(context);
-        default:
-            for (CYHook *hook : GetHooks())
-                if (hook->FromFFI != NULL)
-                    if (JSValueRef value = (*hook->FromFFI)(context, type, ffi, data, initialize, owner))
-                        return value;
+void Aggregate::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    _assert(!overlap);
+
+    uint8_t *base(reinterpret_cast<uint8_t *>(data));
+    JSObjectRef aggregate(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
+    for (size_t index(0); index != signature.count; ++index) {
+        sig::Element *element(&signature.elements[index]);
+        ffi_type *field(ffi->elements[index]);
+
+        JSValueRef rhs;
+        if (aggregate == NULL)
+            rhs = value;
+        else {
+            rhs = CYGetProperty(context, aggregate, index);
+            if (JSValueIsUndefined(context, rhs)) {
+                if (element->name != NULL)
+                    rhs = CYGetProperty(context, aggregate, CYJSString(element->name));
+                else
+                    goto undefined;
+                if (JSValueIsUndefined(context, rhs)) undefined:
+                    throw CYJSError(context, "unable to extract structure value");
+            }
+        }
 
-            CYThrow("unimplemented signature code: '%c''\n", type->primitive);
+        element->type->PoolFFI(pool, context, field, base, rhs);
+        // XXX: alignment?
+        base += field->size;
     }
 }
 
+void Function::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    _assert(false);
+}
+
+#define CYFromFFI_(Type_) \
+template <> \
+JSValueRef Primitive<Type_>::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { \
+    return CYCastJSValue(context, *reinterpret_cast<Type_ *>(data)); \
+}
+
+CYFromFFI_(bool)
+CYFromFFI_(char)
+CYFromFFI_(double)
+CYFromFFI_(float)
+CYFromFFI_(signed char)
+CYFromFFI_(signed int)
+CYFromFFI_(signed long int)
+CYFromFFI_(signed long long int)
+CYFromFFI_(signed short int)
+CYFromFFI_(unsigned char)
+CYFromFFI_(unsigned int)
+CYFromFFI_(unsigned long int)
+CYFromFFI_(unsigned long long int)
+CYFromFFI_(unsigned short int)
+
+JSValueRef Void::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+    return CYJSUndefined(context);
+}
+
+JSValueRef Unknown::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+    _assert(false);
+}
+
+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 CYJSNull(context);
+}
+
+JSValueRef Bits::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+    _assert(false);
+}
+
+JSValueRef Pointer::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+    if (void *value = *reinterpret_cast<void **>(data))
+        return CYMakePointer(context, value, _not(size_t), type, NULL, owner);
+    return CYJSNull(context);
+}
+
+JSValueRef Array::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+    _assert(data != NULL);
+    return CYMakePointer(context, data, size, type, NULL, owner);
+}
+
+JSValueRef Aggregate::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+    return CYMakeStruct(context, data, *this, ffi, owner);
+}
+
+JSValueRef Function::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+    return CYMakeFunctor(context, reinterpret_cast<void (*)()>(data), signature);
+}
+
+}
+
 void CYExecuteClosure(ffi_cif *cif, void *result, void **arguments, void *arg) {
     Closure_privateData *internal(reinterpret_cast<Closure_privateData *>(arg));
 
@@ -854,10 +852,11 @@ void CYExecuteClosure(ffi_cif *cif, void *result, void **arguments, void *arg) {
     JSValueRef values[count];
 
     for (size_t index(0); index != count; ++index)
-        values[index] = CYFromFFI(context, internal->signature_.elements[1 + index].type, internal->cif_.arg_types[index], arguments[index]);
+        values[index] = internal->signature_.elements[1 + index].type->FromFFI(context, internal->cif_.arg_types[index], arguments[index]);
 
     JSValueRef value(internal->adapter_(context, count, values, internal->function_));
-    CYPoolFFI(NULL, context, internal->signature_.elements[0].type, internal->cif_.rtype, result, value);
+    if (internal->cif_.rtype != &ffi_type_void)
+        internal->signature_.elements[0].type->PoolFFI(NULL, context, internal->cif_.rtype, result, value);
 }
 
 static JSValueRef FunctionAdapter_(JSContextRef context, size_t count, JSValueRef values[], JSObjectRef function) {
@@ -952,7 +951,7 @@ static bool CString_setProperty(JSContextRef context, JSObjectRef object, JSStri
 
 static bool Index_(CYPool &pool, JSContextRef context, Struct_privateData *internal, JSStringRef property, ssize_t &index, uint8_t *&base) {
     Type_privateData *typical(internal->type_);
-    sig::Type *type(typical->type_);
+    sig::Aggregate *type(static_cast<sig::Aggregate *>(typical->type_));
     if (type == NULL)
         return false;
 
@@ -960,13 +959,13 @@ static bool Index_(CYPool &pool, JSContextRef context, Struct_privateData *inter
     size_t length(strlen(name));
     double number(CYCastDouble(name, length));
 
-    size_t count(type->data.signature.count);
+    size_t count(type->signature.count);
 
     if (std::isnan(number)) {
         if (property == NULL)
             return false;
 
-        sig::Element *elements(type->data.signature.elements);
+        sig::Element *elements(type->signature.elements);
 
         for (size_t local(0); local != count; ++local) {
             sig::Element *element(&elements[local]);
@@ -1006,7 +1005,12 @@ static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object,
     Type_privateData *typical(internal->type_);
     if (typical->type_ == NULL)
         return NULL;
-    sig::Type &type(*typical->type_);
+
+    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);
+    }
 
     ssize_t offset;
     if (JSStringIsEqualToUTF8CString(property, "$cyi"))
@@ -1014,16 +1018,13 @@ static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object,
     else if (!CYGetOffset(pool, context, property, offset))
         return NULL;
 
-    if (type.primitive == sig::function_P)
-        return CYMakeFunctor(context, reinterpret_cast<void (*)()>(internal->value_), type.data.signature);
-
     ffi_type *ffi(typical->GetFFI());
 
     uint8_t *base(reinterpret_cast<uint8_t *>(internal->value_));
     base += ffi->size * offset;
 
     JSObjectRef owner(internal->GetOwner() ?: object);
-    return CYFromFFI(context, &type, ffi, base, false, owner);
+    return typical->type_->FromFFI(context, ffi, base, false, owner);
 } CYCatch(NULL) }
 
 static bool Pointer_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry {
@@ -1045,25 +1046,26 @@ static bool Pointer_setProperty(JSContextRef context, JSObjectRef object, JSStri
     uint8_t *base(reinterpret_cast<uint8_t *>(internal->value_));
     base += ffi->size * offset;
 
-    CYPoolFFI(NULL, context, typical->type_, ffi, base, value);
+    typical->type_->PoolFFI(NULL, context, ffi, base, value);
     return true;
 } CYCatch(false) }
 
 static JSValueRef Struct_callAsFunction_$cya(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(_this)));
     Type_privateData *typical(internal->type_);
-    return CYMakePointer(context, internal->value_, _not(size_t), typical->type_, typical->ffi_, _this);
+    return CYMakePointer(context, internal->value_, _not(size_t), *typical->type_, typical->ffi_, _this);
 } CYCatch(NULL) }
 
 static JSValueRef Struct_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(object)));
-    return CYMakeType(context, internal->type_->type_);
+    return CYMakeType(context, *internal->type_->type_);
 } CYCatch(NULL) }
 
 static JSValueRef Struct_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     CYPool pool;
     Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(object)));
     Type_privateData *typical(internal->type_);
+    sig::Aggregate *type(static_cast<sig::Aggregate *>(typical->type_));
 
     ssize_t index;
     uint8_t *base;
@@ -1073,13 +1075,14 @@ static JSValueRef Struct_getProperty(JSContextRef context, JSObjectRef object, J
 
     JSObjectRef owner(internal->GetOwner() ?: object);
 
-    return CYFromFFI(context, typical->type_->data.signature.elements[index].type, typical->GetFFI()->elements[index], base, false, owner);
+    return type->signature.elements[index].type->FromFFI(context, typical->GetFFI()->elements[index], base, false, owner);
 } CYCatch(NULL) }
 
 static bool Struct_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry {
     CYPool pool;
     Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(object)));
     Type_privateData *typical(internal->type_);
+    sig::Aggregate *type(static_cast<sig::Aggregate *>(typical->type_));
 
     ssize_t index;
     uint8_t *base;
@@ -1087,20 +1090,20 @@ static bool Struct_setProperty(JSContextRef context, JSObjectRef object, JSStrin
     if (!Index_(pool, context, internal, property, index, base))
         return false;
 
-    CYPoolFFI(NULL, context, typical->type_->data.signature.elements[index].type, typical->GetFFI()->elements[index], base, value);
+    type->signature.elements[index].type->PoolFFI(NULL, context, typical->GetFFI()->elements[index], base, value);
     return true;
 } CYCatch(false) }
 
 static void Struct_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) {
     Struct_privateData *internal(reinterpret_cast<Struct_privateData *>(JSObjectGetPrivate(object)));
     Type_privateData *typical(internal->type_);
-    sig::Type *type(typical->type_);
+    sig::Aggregate *type(static_cast<sig::Aggregate *>(typical->type_));
 
     if (type == NULL)
         return;
 
-    size_t count(type->data.signature.count);
-    sig::Element *elements(type->data.signature.elements);
+    size_t count(type->signature.count);
+    sig::Element *elements(type->signature.elements);
 
     char number[32];
 
@@ -1134,7 +1137,7 @@ JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, voi
         ffi_type *ffi(cif->arg_types[index]);
         // XXX: alignment?
         values[index] = new(pool) uint8_t[ffi->size];
-        CYPoolFFI(&pool, context, element->type, ffi, values[index], arguments[index - setups]);
+        element->type->PoolFFI(&pool, context, ffi, values[index], arguments[index - setups]);
     }
 
     uint8_t value[cif->rtype->size];
@@ -1146,7 +1149,7 @@ JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, voi
             call = hook->CallFunction;
 
     call(pool, context, cif, function, value, values);
-    return CYFromFFI(context, signature->elements[0].type, 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 {
@@ -1157,33 +1160,22 @@ static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef objec
 
 static JSValueRef Pointer_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(object)));
-    if (internal->type_->type_->primitive != sig::function_P)
+    if (dynamic_cast<sig::Function *>(internal->type_->type_) == NULL)
         throw CYJSError(context, "cannot call a pointer to non-function");
     JSObjectRef functor(CYCastJSObject(context, CYGetProperty(context, object, cyi_s)));
     return CYCallAsFunction(context, functor, _this, count, arguments);
 } CYCatch(NULL) }
 
-JSObjectRef CYMakeType(JSContextRef context, sig::Primitive primitive) {
-    Type_privateData *internal(new Type_privateData(primitive));
-    return JSObjectMake(context, Type_privateData::Class_, internal);
-}
-
-JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) {
+JSObjectRef CYMakeType(JSContextRef context, const sig::Type &type) {
     Type_privateData *internal(new Type_privateData(type));
     return JSObjectMake(context, Type_privateData::Class_, internal);
 }
 
 JSObjectRef CYMakeType(JSContextRef context, sig::Signature *signature) {
     CYPool pool;
-
-    sig::Type type;
-    type.name = NULL;
-    type.flags = 0;
-
-    type.primitive = sig::function_P;
-    sig::Copy(pool, type.data.signature, *signature);
-
-    return CYMakeType(context, &type);
+    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) {
@@ -1355,7 +1347,7 @@ static JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t
     sig::Signature signature;
     sig::Parse(pool, &signature, type, &Structor_);
 
-    return CYMakePointer(context, value, _not(size_t), signature.elements[0].type, NULL, NULL);
+    return CYMakePointer(context, value, _not(size_t), *signature.elements[0].type, NULL, NULL);
 } CYCatch(NULL) }
 
 static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1366,23 +1358,19 @@ static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t cou
         const char *encoding(CYPoolCString(pool, context, arguments[0]));
         sig::Signature signature;
         sig::Parse(pool, &signature, encoding, &Structor_);
-        return CYMakeType(context, signature.elements[0].type);
+        return CYMakeType(context, *signature.elements[0].type);
     } else if (count == 2) {
         JSObjectRef types(CYCastJSObject(context, arguments[0]));
         size_t count(CYArrayLength(context, types));
 
         JSObjectRef names(CYCastJSObject(context, arguments[1]));
 
-        sig::Type type;
-        type.name = NULL;
-        type.flags = 0;
-
-        type.primitive = sig::struct_P;
-        type.data.signature.elements = new(pool) sig::Element[count];
-        type.data.signature.count = count;
+        sig::Aggregate type(false);
+        type.signature.elements = new(pool) sig::Element[count];
+        type.signature.count = count;
 
         for (size_t i(0); i != count; ++i) {
-            sig::Element &element(type.data.signature.elements[i]);
+            sig::Element &element(type.signature.elements[i]);
             element.offset = _not(size_t);
 
             JSValueRef name(CYArrayGet(context, names, i));
@@ -1397,31 +1385,26 @@ static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t cou
             element.type = internal->type_;
         }
 
-        return CYMakeType(context, &type);
+        return CYMakeType(context, type);
     } else {
         throw CYJSError(context, "incorrect number of arguments to Type constructor");
     }
 } CYCatch(NULL) }
 
-static JSValueRef Type_callAsFunction_$With(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], sig::Primitive primitive, JSValueRef *exception) { CYTry {
+static JSValueRef Type_callAsFunction_$With(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], sig::Callable &type, JSValueRef *exception) { CYTry {
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
 
     CYPool pool;
 
-    sig::Type type;
-    type.name = NULL;
-    type.flags = 0;
+    type.signature.elements = new(pool) sig::Element[1 + count];
+    type.signature.count = 1 + count;
 
-    type.primitive = primitive;
-    type.data.signature.elements = new(pool) sig::Element[1 + count];
-    type.data.signature.count = 1 + count;
-
-    type.data.signature.elements[0].name = NULL;
-    type.data.signature.elements[0].type = internal->type_;
-    type.data.signature.elements[0].offset = _not(size_t);
+    type.signature.elements[0].name = NULL;
+    type.signature.elements[0].type = internal->type_;
+    type.signature.elements[0].offset = _not(size_t);
 
     for (size_t i(0); i != count; ++i) {
-        sig::Element &element(type.data.signature.elements[i + 1]);
+        sig::Element &element(type.signature.elements[i + 1]);
         element.name = NULL;
         element.offset = _not(size_t);
 
@@ -1432,7 +1415,7 @@ static JSValueRef Type_callAsFunction_$With(JSContextRef context, JSObjectRef ob
         element.type = internal->type_;
     }
 
-    return CYMakeType(context, &type);
+    return CYMakeType(context, type);
 } CYCatch(NULL) }
 
 static JSValueRef Type_callAsFunction_arrayOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1445,19 +1428,13 @@ static JSValueRef Type_callAsFunction_arrayOf(JSContextRef context, JSObjectRef
     if (index == _not(size_t))
         throw CYJSError(context, "invalid array size used with Type.arrayOf");
 
-    sig::Type type;
-    type.name = NULL;
-    type.flags = 0;
-
-    type.primitive = sig::array_P;
-    type.data.data.type = internal->type_;
-    type.data.data.size = index;
-
-    return CYMakeType(context, &type);
+    sig::Array type(*internal->type_, index);
+    return CYMakeType(context, type);
 } CYCatch(NULL) }
 
 static JSValueRef Type_callAsFunction_blockWith(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
-    return Type_callAsFunction_$With(context, object, _this, count, arguments, sig::block_P, exception);
+    sig::Block type;
+    return Type_callAsFunction_$With(context, object, _this, count, arguments, type, exception);
 }
 
 static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1465,85 +1442,15 @@ static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef
         throw CYJSError(context, "incorrect number of arguments to Type.constant");
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
 
-    sig::Type type(*internal->type_);
-    type.flags |= JOC_TYPE_CONST;
-    return CYMakeType(context, &type);
-} CYCatch(NULL) }
-
-static JSValueRef Type_callAsFunction_long(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    if (count != 0)
-        throw CYJSError(context, "incorrect number of arguments to Type.long");
-    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
-
-    sig::Type type(*internal->type_);
-
-    switch (type.primitive) {
-        case sig::short_P: type.primitive = sig::int_P; break;
-        case sig::int_P: type.primitive = sig::long_P; break;
-        case sig::long_P: type.primitive = sig::longlong_P; break;
-        default: throw CYJSError(context, "invalid type argument to Type.long");
-    }
-
-    return CYMakeType(context, &type);
-} CYCatch(NULL) }
-
-static JSValueRef Type_callAsFunction_short(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    if (count != 0)
-        throw CYJSError(context, "incorrect number of arguments to Type.short");
-    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
-
-    sig::Type type(*internal->type_);
-
-    switch (type.primitive) {
-        case sig::int_P: type.primitive = sig::short_P; break;
-        case sig::long_P: type.primitive = sig::int_P; break;
-        case sig::longlong_P: type.primitive = sig::long_P; break;
-        default: throw CYJSError(context, "invalid type argument to Type.short");
-    }
-
-    return CYMakeType(context, &type);
-} CYCatch(NULL) }
-
-static JSValueRef Type_callAsFunction_signed(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    if (count != 0)
-        throw CYJSError(context, "incorrect number of arguments to Type.signed");
-    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
-
-    sig::Type type(*internal->type_);
-
-    switch (type.primitive) {
-        case sig::char_P: case sig::schar_P: case sig::uchar_P: type.primitive = sig::schar_P; break;
-        case sig::short_P: case sig::ushort_P: type.primitive = sig::short_P; break;
-        case sig::int_P: case sig::uint_P: type.primitive = sig::int_P; break;
-        case sig::long_P: case sig::ulong_P: type.primitive = sig::long_P; break;
-        case sig::longlong_P: case sig::ulonglong_P: type.primitive = sig::longlong_P; break;
-        default: throw CYJSError(context, "invalid type argument to Type.signed");
-    }
-
-    return CYMakeType(context, &type);
-} CYCatch(NULL) }
-
-static JSValueRef Type_callAsFunction_unsigned(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    if (count != 0)
-        throw CYJSError(context, "incorrect number of arguments to Type.unsigned");
-    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
-
-    sig::Type type(*internal->type_);
-
-    switch (type.primitive) {
-        case sig::char_P: case sig::schar_P: case sig::uchar_P: type.primitive = sig::uchar_P; break;
-        case sig::short_P: case sig::ushort_P: type.primitive = sig::ushort_P; break;
-        case sig::int_P: case sig::uint_P: type.primitive = sig::uint_P; break;
-        case sig::long_P: case sig::ulong_P: type.primitive = sig::ulong_P; break;
-        case sig::longlong_P: case sig::ulonglong_P: type.primitive = sig::ulonglong_P; break;
-        default: throw CYJSError(context, "invalid type argument to Type.unsigned");
-    }
-
-    return CYMakeType(context, &type);
+    CYPool pool;
+    sig::Type *type(internal->type_->Copy(pool));
+    type->flags |= JOC_TYPE_CONST;
+    return CYMakeType(context, *type);
 } CYCatch(NULL) }
 
 static JSValueRef Type_callAsFunction_functionWith(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
-    return Type_callAsFunction_$With(context, object, _this, count, arguments, sig::function_P, exception);
+    sig::Function type;
+    return Type_callAsFunction_$With(context, object, _this, count, arguments, type, exception);
 }
 
 static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1551,22 +1458,10 @@ static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRe
         throw CYJSError(context, "incorrect number of arguments to Type.pointerTo");
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
 
-    sig::Type type;
-    type.name = NULL;
-
-    if (internal->type_->primitive == sig::char_P) {
-        type.flags = internal->type_->flags;
-        type.primitive = sig::string_P;
-        type.data.data.type = NULL;
-        type.data.data.size = 0;
-    } else {
-        type.flags = 0;
-        type.primitive = sig::pointer_P;
-        type.data.data.type = internal->type_;
-        type.data.data.size = 0;
-    }
-
-    return CYMakeType(context, &type);
+    if (dynamic_cast<sig::Primitive<char> *>(internal->type_) != NULL)
+        return CYMakeType(context, sig::String());
+    else
+        return CYMakeType(context, sig::Pointer(*internal->type_));
 } CYCatch(NULL) }
 
 static JSValueRef Type_callAsFunction_withName(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1575,11 +1470,7 @@ static JSValueRef Type_callAsFunction_withName(JSContextRef context, JSObjectRef
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
 
     CYPool pool;
-    const char *name(CYPoolCString(pool, context, arguments[0]));
-
-    sig::Type type(*internal->type_);
-    type.name = name;
-    return CYMakeType(context, &type);
+    return CYMakeType(context, *internal->type_->Copy(pool, CYPoolCString(pool, context, arguments[0])));
 } CYCatch(NULL) }
 
 static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1587,16 +1478,16 @@ static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object,
         throw CYJSError(context, "incorrect number of arguments to type cast function");
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
 
-    if (internal->type_->primitive == sig::function_P)
-        return CYMakeFunctor(context, arguments[0], internal->type_->data.signature);
+    if (sig::Function *function = dynamic_cast<sig::Function *>(internal->type_))
+        return CYMakeFunctor(context, arguments[0], function->signature);
 
     sig::Type *type(internal->type_);
     ffi_type *ffi(internal->GetFFI());
     // XXX: alignment?
     uint8_t value[ffi->size];
     CYPool pool;
-    CYPoolFFI(&pool, context, type, ffi, value, arguments[0]);
-    return CYFromFFI(context, type, ffi, value);
+    type->PoolFFI(&pool, context, ffi, value, arguments[0]);
+    return type->FromFFI(context, ffi, value);
 } CYCatch(NULL) }
 
 static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1605,16 +1496,9 @@ static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef obje
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
 
     sig::Type *type(internal->type_);
-    size_t length;
+    size_t length(type->Translate(type));
 
-    if (type->primitive != sig::array_P)
-        length = _not(size_t);
-    else {
-        length = type->data.data.size;
-        type = type->data.data.type;
-    }
-
-    JSObjectRef pointer(CYMakePointer(context, NULL, length, type, NULL, NULL));
+    JSObjectRef pointer(CYMakePointer(context, NULL, length, *type, NULL, NULL));
     Pointer *value(reinterpret_cast<Pointer *>(JSObjectGetPrivate(pointer)));
     value->value_ = value->pool_->malloc<void>(internal->GetFFI()->size);
     memset(value->value_, 0, internal->GetFFI()->size);
@@ -1633,30 +1517,17 @@ static JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t
 
 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)));
-
-    sig::Type type;
-    type.name = NULL;
-    type.flags = 0;
-
-    type.primitive = sig::char_P;
-    type.data.data.type = NULL;
-    type.data.data.size = 0;
-
-    return CYMakePointer(context, internal->value_, _not(size_t), &type, NULL, NULL);
+    return CYMakePointer(context, internal->value_, _not(size_t), sig::Primitive<char>(), NULL, NULL);
 } CYCatch(NULL) }
 
 static JSValueRef Functor_callAsFunction_$cya(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(_this)));
 
-    sig::Type type;
-    type.name = NULL;
-    type.flags = 0;
-
-    type.primitive = sig::function_P;
-    sig::Copy(pool, type.data.signature, internal->signature_);
+    sig::Function type;
+    sig::Copy(pool, type.signature, internal->signature_);
 
-    return CYMakePointer(context, internal->value_, _not(size_t), &type, NULL, NULL);
+    return CYMakePointer(context, internal->value_, _not(size_t), type, NULL, NULL);
 } CYCatch(NULL) }
 
 static JSValueRef Pointer_callAsFunction_toPointer(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1698,34 +1569,30 @@ static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRe
         JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype")));
         JSObjectRef toCYON(CYCastJSObject(context, CYGetProperty(context, Array, toCYON_s)));
         return CYCallAsFunction(context, toCYON, _this, count, arguments);
-    } else if (internal->type_->type_ == NULL) pointer: {
-        CYLocalPool pool;
-        std::ostringstream str;
-
-        sig::Type type;
-        type.name = NULL;
-        type.flags = 0;
-
-        type.primitive = sig::pointer_P;
-        type.data.data.type = internal->type_->type_;
-        type.data.data.size = 0;
-
-        CYOptions options;
-        CYOutput output(*str.rdbuf(), options);
-        (new(pool) CYTypeExpression(Decode(pool, &type)))->Output(output, CYNoFlags);
-
-        str << "(" << internal->value_ << ")";
-        std::string value(str.str());
-        return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size())));
-    } else try {
+    }
+
+    try {
         JSValueRef value(CYGetProperty(context, _this, cyi_s));
-        if (JSValueIsUndefined(context, value))
-            goto pointer;
-        CYPool pool;
-        return CYCastJSValue(context, pool.strcat("&", CYPoolCCYON(pool, context, value, objects), NULL));
+        if (!JSValueIsUndefined(context, value)) {
+            CYPool pool;
+            return CYCastJSValue(context, pool.strcat("&", CYPoolCCYON(pool, context, value, objects), NULL));
+        }
     } catch (const CYException &e) {
-        goto pointer;
+        // XXX: it might be interesting to include this error
     }
+
+    CYLocalPool pool;
+    std::ostringstream str;
+
+    sig::Pointer type(*internal->type_->type_);
+
+    CYOptions options;
+    CYOutput output(*str.rdbuf(), options);
+    (new(pool) CYTypeExpression(CYDecodeType(pool, &type)))->Output(output, CYNoFlags);
+
+    str << "(" << internal->value_ << ")";
+    std::string value(str.str());
+    return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size())));
 } CYCatch(NULL) }
 
 static JSValueRef CString_getProperty_length(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
@@ -1735,29 +1602,13 @@ static JSValueRef CString_getProperty_length(JSContextRef context, JSObjectRef o
 } CYCatch(NULL) }
 
 static JSValueRef CString_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
-    sig::Type type;
-    type.name = NULL;
-    type.flags = 0;
-
-    type.primitive = sig::char_P;
-    type.data.data.type = NULL;
-    type.data.data.size = 0;
-
-    return CYMakeType(context, &type);
+    return CYMakeType(context, sig::String());
 } CYCatch(NULL) }
 
 static JSValueRef Pointer_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(object)));
-
-    sig::Type type;
-    type.name = NULL;
-    type.flags = 0;
-
-    type.primitive = sig::pointer_P;
-    type.data.data.type = internal->type_->type_;
-    type.data.data.size = 0;
-
-    return CYMakeType(context, &type);
+    sig::Pointer type(*internal->type_->type_);
+    return CYMakeType(context, type);
 } CYCatch(NULL) }
 
 static JSValueRef CString_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1792,7 +1643,7 @@ static JSValueRef Type_getProperty_alignment(JSContextRef context, JSObjectRef o
 
 static JSValueRef Type_getProperty_name(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
-    return CYCastJSValue(context, internal->type_->name);
+    return CYCastJSValue(context, internal->type_->GetName());
 } CYCatch(NULL) }
 
 static JSValueRef Type_getProperty_size(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
@@ -1813,7 +1664,7 @@ static JSValueRef Type_callAsFunction_toCYON(JSContextRef context, JSObjectRef o
     std::stringbuf out;
     CYOptions options;
     CYOutput output(out, options);
-    (new(pool) CYTypeExpression(Decode(pool, internal->type_)))->Output(output, CYNoFlags);
+    (new(pool) CYTypeExpression(CYDecodeType(pool, internal->type_)))->Output(output, CYNoFlags);
     return CYCastJSValue(context, CYJSString(out.str().c_str()));
 } CYCatch(NULL) }
 
@@ -1892,20 +1743,16 @@ static JSStaticValue Type_staticValues[4] = {
     {NULL, NULL, NULL, 0}
 };
 
-static JSStaticFunction Type_staticFunctions[14] = {
+static JSStaticFunction Type_staticFunctions[10] = {
     {"arrayOf", &Type_callAsFunction_arrayOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"blockWith", &Type_callAsFunction_blockWith, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"constant", &Type_callAsFunction_constant, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"functionWith", &Type_callAsFunction_functionWith, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {"long", &Type_callAsFunction_long, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"pointerTo", &Type_callAsFunction_pointerTo, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {"short", &Type_callAsFunction_short, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {"signed", &Type_callAsFunction_signed, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"withName", &Type_callAsFunction_withName, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"toCYON", &Type_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"toJSON", &Type_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"toString", &Type_callAsFunction_toString, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
-    {"unsigned", &Type_callAsFunction_unsigned, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {NULL, NULL, 0}
 };
 
@@ -2348,13 +2195,23 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) {
 
     CYSetProperty(context, cache, CYJSString("NULL"), CYJSNull(context), kJSPropertyAttributeDontEnum);
 
-    CYSetProperty(context, cache, CYJSString("bool"), CYMakeType(context, sig::boolean_P), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("char"), CYMakeType(context, sig::char_P), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("short"), CYMakeType(context, sig::short_P), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("int"), CYMakeType(context, sig::int_P), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("long"), CYMakeType(context, sig::long_P), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("float"), CYMakeType(context, sig::float_P), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("double"), CYMakeType(context, sig::double_P), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("bool"), CYMakeType(context, sig::Primitive<bool>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("char"), CYMakeType(context, sig::Primitive<char>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("schar"), CYMakeType(context, sig::Primitive<signed char>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("uchar"), CYMakeType(context, sig::Primitive<unsigned char>()), kJSPropertyAttributeDontEnum);
+
+    CYSetProperty(context, cache, CYJSString("short"), CYMakeType(context, sig::Primitive<short>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("int"), CYMakeType(context, sig::Primitive<int>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("long"), CYMakeType(context, sig::Primitive<long>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("longlong"), CYMakeType(context, sig::Primitive<long long>()), kJSPropertyAttributeDontEnum);
+
+    CYSetProperty(context, cache, CYJSString("ushort"), CYMakeType(context, sig::Primitive<unsigned short>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("uint"), CYMakeType(context, sig::Primitive<unsigned int>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("ulong"), CYMakeType(context, sig::Primitive<unsigned long>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("ulonglong"), CYMakeType(context, sig::Primitive<unsigned long long>()), kJSPropertyAttributeDontEnum);
+
+    CYSetProperty(context, cache, CYJSString("float"), CYMakeType(context, sig::Primitive<float>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("double"), CYMakeType(context, sig::Primitive<double>()), kJSPropertyAttributeDontEnum);
 
     for (CYHook *hook : GetHooks())
         if (hook->SetupContext != NULL)
index 87ff05557593bda675f8ffe27dd5c9ceb51cac38..0851dea225467b3a65ab0954d831cd6d2fb5a9cd 100644 (file)
@@ -33,9 +33,7 @@
 #include "Pooling.hpp"
 
 JSGlobalContextRef CYGetJSContext(JSContextRef context);
-void Structor_(CYPool &pool, sig::Type *&type);
-
-JSObjectRef CYMakeType(JSContextRef context, sig::Type *type);
+sig::Type *Structor_(CYPool &pool, sig::Aggregate *aggregate);
 
 extern JSClassRef Functor_;
 
@@ -47,11 +45,6 @@ struct Type_privateData :
     ffi_type *ffi_;
     sig::Type *type_;
 
-    void Set(sig::Type *type) {
-        type_ = new(*pool_) sig::Type;
-        sig::Copy(*pool_, *type_, *type);
-    }
-
     Type_privateData(const char *type) :
         ffi_(NULL)
     {
@@ -60,27 +53,16 @@ struct Type_privateData :
         type_ = signature.elements[0].type;
     }
 
-    Type_privateData(sig::Primitive primitive) :
-        ffi_(NULL)
+    Type_privateData(const sig::Type &type, ffi_type *ffi = NULL) :
+        type_(type.Copy(*pool_))
     {
-        sig::Type type;
-        memset(&type, 0, sizeof(type));
-        type.primitive = primitive;
-        Set(&type);
-    }
 
-    Type_privateData(sig::Type *type) :
-        ffi_(NULL)
-    {
-        // XXX: just in case I messed up migrating
-        _assert(type != NULL);
-        Set(type);
-    }
-
-    Type_privateData(sig::Type *type, ffi_type *ffi) {
-        ffi_ = new(*pool_) ffi_type;
-        sig::Copy(*pool_, *ffi_, *ffi);
-        Set(type);
+        if (ffi == NULL)
+            ffi_ = NULL;
+        else {
+            ffi_ = new(*pool_) ffi_type;
+            sig::Copy(*pool_, *ffi_, *ffi);
+        }
     }
 
     ffi_type *GetFFI() {
@@ -95,7 +77,7 @@ struct Type_privateData :
             signature.count = 1;
 
             ffi_cif cif;
-            sig::sig_ffi_cif(*pool_, &sig::ObjectiveC, &signature, &cif);
+            sig::sig_ffi_cif(*pool_, &signature, &cif);
 
             ffi_ = new(*pool_) ffi_type;
             *ffi_ = *cif.rtype;
@@ -163,7 +145,7 @@ struct Functor :
 {
   private:
     void set() {
-        sig::sig_ffi_cif(*pool_, &sig::ObjectiveC, &signature_, &cif_);
+        sig::sig_ffi_cif(*pool_, &signature_, &cif_);
     }
 
   public:
index b501cf2c983242a516947d3e66b35a27d3174cc7..43c6be020ec6c196b8209e2ba8786a83ade6b149 100644 (file)
@@ -110,9 +110,6 @@ _finline Type_ CYCastPointer(JSContextRef context, JSValueRef value, bool *guess
     return reinterpret_cast<Type_>(CYCastPointer_(context, value, guess));
 }
 
-void CYPoolFFI(CYPool *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value);
-JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize = false, JSObjectRef owner = NULL);
-
 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)());
 
@@ -131,9 +128,6 @@ struct CYHook {
     void (*Initialize)();
     void (*SetupContext)(JSContextRef);
 
-    bool (*PoolFFI)(CYPool *, JSContextRef, sig::Type *, ffi_type *, void *, JSValueRef);
-    JSValueRef (*FromFFI)(JSContextRef, sig::Type *, ffi_type *, void *, bool, JSObjectRef);
-
     void *(*CastSymbol)(const char *);
 };
 
@@ -141,10 +135,9 @@ struct CYRegisterHook {
     CYRegisterHook(CYHook *hook);
 };
 
-JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, sig::Type *type, ffi_type *ffi, JSObjectRef owner);
+JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, const sig::Type &type, ffi_type *ffi, JSObjectRef owner);
 
-JSObjectRef CYMakeType(JSContextRef context, sig::Primitive primitive);
-JSObjectRef CYMakeType(JSContextRef context, sig::Type *type);
+JSObjectRef CYMakeType(JSContextRef context, const sig::Type &type);
 JSObjectRef CYMakeType(JSContextRef context, sig::Signature *signature);
 
 void CYFinalize(JSObjectRef object);
index b185bf705e6f99b20a6f297cc055d13f405beb7e..a21aa6ea9016461dc6df8dd8e7aedd95978e0d1c 100644 (file)
@@ -861,23 +861,15 @@ static sig::Signature *CYBlockSignature(CYPool &pool, NSBlock *self);
         return [super cy$toCYON:objective inSet:objects];
     _oassert(objects.insert(self).second);
 
-    // XXX: maybe move this id check into Decode's implementation for block_P
-    _assert(signature->count >= 2);
-    _assert(signature->elements[1].type->primitive == sig::object_P);
+    sig::Block type;
+    sig::Copy(pool, type.signature, *signature);
 
-    sig::Type type;
-    type.name = NULL;
-    type.flags = 0;
-
-    type.primitive = sig::function_P; // XXX: sig::block_P
-    sig::Copy(pool, type.data.signature, *signature);
-
-    CYTypedIdentifier *typed((new(pool) CYTypeExpression(Decode(pool, &type)))->typed_);
+    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_->next_, NULL));
+    CYObjCBlock *block(new(pool) CYObjCBlock(typed, function->parameters_, NULL));
 
     std::ostringstream str;
     CYOptions options;
@@ -1272,12 +1264,11 @@ NSArray *CYCastNSArray(JSContextRef context, JSPropertyNameArrayRef names) {
     return array;
 }
 
-JSValueRef CYCastJSValue(JSContextRef context, NSObject *value) { CYPoolTry {
+JSValueRef CYCastJSValue(JSContextRef context, NSObject *value) {
     if (value == nil)
         return CYJSNull(context);
-    else
-        return CYMakeInstance(context, value);
-} CYPoolCatch(NULL) return /*XXX*/ NULL; }
+    return CYMakeInstance(context, value);
+}
 
 @implementation CYJSObject
 
@@ -1501,6 +1492,12 @@ static JSObjectRef CYMakeSelector(JSContextRef context, SEL sel) {
     return JSObjectMake(context, Selector_, internal);
 }
 
+static JSValueRef CYCastJSValue(JSContextRef context, SEL sel) {
+    if (sel == NULL)
+        return CYJSNull(context);
+    return CYMakeSelector(context, sel);
+}
+
 static SEL CYCastSEL(JSContextRef context, JSValueRef value) {
     if (JSValueIsObjectOfClass(context, value, Selector_)) {
         Selector_privateData *internal(reinterpret_cast<Selector_privateData *>(JSObjectGetPrivate((JSObjectRef) value)));
@@ -1523,8 +1520,8 @@ static void CYObjectiveC_CallFunction(CYPool &pool, JSContextRef context, ffi_ci
     CYCallFunction(pool, context, cif, function, value, values);
 } CYSadCatch() }
 
+static NSBlock *CYCastNSBlock(CYPool &pool, JSContextRef context, JSValueRef value, const sig::Signature *signature) {
 #ifdef __APPLE__
-static NSBlock *CYCastNSBlock(CYPool &pool, JSContextRef context, JSValueRef value, sig::Signature *signature) {
     if (JSValueIsNull(context, value))
         return nil;
     JSObjectRef object(CYCastJSObject(context, value));
@@ -1550,82 +1547,71 @@ static NSBlock *CYCastNSBlock(CYPool &pool, JSContextRef context, JSValueRef val
     memcpy(modified.elements + 2, signature->elements + 1, sizeof(sig::Element) * (signature->count - 1));
 
     modified.elements[1].name = NULL;
-    modified.elements[1].type = new(pool) sig::Type();
+    modified.elements[1].type = new(pool) sig::Object();
     modified.elements[1].offset = _not(size_t);
 
-    memset(modified.elements[1].type, 0, sizeof(sig::Type));
-    modified.elements[1].type->primitive = sig::object_P;
-
     return CYMakeBlock(context, object, modified);
-}
+#else
+    _assert(false);
 #endif
+}
 
-static bool CYObjectiveC_PoolFFI(CYPool *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value) { CYSadTry {
-    // XXX: assigning to an indirect id * works for return values, but not for properties and fields
+namespace sig {
 
-    switch (type->primitive) {
-#ifdef __APPLE__
-        case sig::block_P:
-            // XXX: this function might not handle the idea of a null pool
-            *reinterpret_cast<id *>(data) = CYCastNSBlock(*pool, context, value, &type->data.signature);
-        break;
-#endif
+void Block::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    // XXX: this function might not handle the idea of a null pool
+    *reinterpret_cast<id *>(data) = CYCastNSBlock(*pool, context, value, &signature);
+}
 
-        case sig::object_P:
-        case sig::typename_P:
-            *reinterpret_cast<id *>(data) = CYCastNSObject(pool, context, value);
-        break;
+// XXX: assigning to an indirect id * works for return values, but not for properties and fields
+void Object::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    *reinterpret_cast<id *>(data) = CYCastNSObject(pool, context, value);
+}
 
-        case sig::selector_P:
-            *reinterpret_cast<SEL *>(data) = CYCastSEL(context, value);
-        break;
+void Meta::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    *reinterpret_cast<id *>(data) = CYCastNSObject(pool, context, value);
+}
 
-        default:
-            return false;
-    }
+void Selector::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    *reinterpret_cast<SEL *>(data) = CYCastSEL(context, value);
+}
 
-    return true;
-} CYSadCatch(false) }
-
-static JSValueRef CYObjectiveC_FromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) { CYPoolTry {
-    switch (type->primitive) {
-        // XXX: do something epic about blocks
-        case sig::block_P:
-        case sig::object_P:
-            if (NSObject *value = *reinterpret_cast<NSObject **>(data)) {
-                JSObjectRef object(CYMakeInstance(context, value));
-
-                if (initialize) {
-                    Instance *internal(reinterpret_cast<Instance *>(JSObjectGetPrivate(object)));
-
-                    if ((internal->flags_ & Instance::Uninitialized) != 0) {
-                        internal->flags_ = static_cast<Instance::Flags>(internal->flags_ & ~Instance::Uninitialized);
-                        _assert(internal->value_ == nil);
-                        internal->value_ = value;
-                    }
-
-                    [value release];
-                }
-
-                return object;
-            } else goto null;
-
-        case sig::typename_P:
-            if (Class value = *reinterpret_cast<Class *>(data))
-                return CYMakeInstance(context, value, Instance::Permanent);
-            else goto null;
-
-        case sig::selector_P:
-            if (SEL value = *reinterpret_cast<SEL *>(data))
-                return CYMakeSelector(context, value);
-            else goto null;
-
-        null:
-            return CYJSNull(context);
-        default:
-            return NULL;
+JSValueRef Object::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+    NSObject *value(*reinterpret_cast<NSObject **>(data));
+    if (value == NULL)
+        return CYJSNull(context);
+    JSObjectRef object(CYMakeInstance(context, value));
+
+    if (initialize) {
+        Instance *internal(reinterpret_cast<Instance *>(JSObjectGetPrivate(object)));
+
+        if ((internal->flags_ & Instance::Uninitialized) != 0) {
+            internal->flags_ = static_cast<Instance::Flags>(internal->flags_ & ~Instance::Uninitialized);
+            _assert(internal->value_ == nil);
+            internal->value_ = value;
+        }
+
+        [value release];
     }
-} CYPoolCatch(NULL) return /*XXX*/ NULL; }
+
+    return object;
+}
+
+JSValueRef Meta::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+    if (Class value = *reinterpret_cast<Class *>(data))
+        return CYMakeInstance(context, value, Instance::Permanent);
+    return CYJSNull(context);
+}
+
+JSValueRef Selector::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+    return CYCastJSValue(context, *reinterpret_cast<SEL *>(data));
+}
+
+JSValueRef Block::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
+    return CYCastJSValue(context, *reinterpret_cast<NSObject **>(data));
+}
+
+}
 
 static bool CYImplements(id object, Class _class, SEL selector, bool devoid = false) {
     if (objc_method *method = class_getInstanceMethod(_class, selector)) {
@@ -1970,7 +1956,7 @@ static JSValueRef FunctionInstance_callAsFunction(JSContextRef context, JSObject
         sig::Parse(pool, &signature, encoding, &Structor_);
 
         ffi_cif cif;
-        sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif);
+        sig::sig_ffi_cif(pool, &signature, &cif);
 
         BlockLiteral *literal(reinterpret_cast<BlockLiteral *>(self));
         void (*function)() = reinterpret_cast<void (*)()>(literal->invoke);
@@ -2072,7 +2058,7 @@ static JSValueRef Internal_getProperty(JSContextRef context, JSObjectRef object,
 #endif
 
             auto type(new(pool) Type_privateData(encoding));
-            return CYFromFFI(context, type->type_, type->GetFFI(), data);
+            return type->type_->FromFFI(context, type->GetFFI(), data);
         }
     }
 
@@ -2101,7 +2087,7 @@ static bool Internal_setProperty(JSContextRef context, JSObjectRef object, JSStr
             field = field & ~(mask << shift) | (uintptr_t(CYCastDouble(context, value)) & mask) << shift;
         } else {
             auto type(new(pool) Type_privateData(ivar_getTypeEncoding(ivar)));
-            CYPoolFFI(&pool, context, type->type_, type->GetFFI(), reinterpret_cast<uint8_t *>(self) + ivar_getOffset(ivar), value);
+            type->type_->PoolFFI(&pool, context, type->GetFFI(), reinterpret_cast<uint8_t *>(self) + ivar_getOffset(ivar), value);
             return true;
         }
     }
@@ -2432,11 +2418,7 @@ JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class _cla
             sig::Element *element(&elements[index]);
             element->name = NULL;
             element->offset = _not(size_t);
-
-            sig::Type *type(new (pool) sig::Type);
-            memset(type, 0, sizeof(*type));
-            type->primitive = sig::object_P;
-            element->type = type;
+            element->type = new(pool) sig::Object();
         }
 
         signature.elements = elements;
@@ -2444,7 +2426,7 @@ JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class _cla
     }
 
     ffi_cif cif;
-    sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif);
+    sig::sig_ffi_cif(pool, &signature, &cif);
 
     if (imp == NULL) {
 #ifndef CY_NO_STRET
@@ -2555,18 +2537,20 @@ static JSValueRef CYValue_callAsFunction_$cya(JSContextRef context, JSObjectRef
     CYValue *internal(reinterpret_cast<CYValue *>(JSObjectGetPrivate(_this)));
     Type_privateData *typical(internal->GetType());
 
+    sig::Void XXX;
+
     sig::Type *type;
     ffi_type *ffi;
 
     if (typical == NULL) {
-        type = NULL;
+        type = &XXX;
         ffi = NULL;
     } else {
         type = typical->type_;
         ffi = typical->ffi_;
     }
 
-    return CYMakePointer(context, &internal->value_, _not(size_t), type, ffi, object);
+    return CYMakePointer(context, &internal->value_, _not(size_t), *type, ffi, object);
 } CYCatch(NULL) }
 
 static JSValueRef FunctionInstance_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
@@ -2681,11 +2665,8 @@ static JSValueRef Class_callAsFunction_pointerTo(JSContextRef context, JSObjectR
     if (!CYIsClass(value))
         CYThrow("non-Class object cannot be used as Type");
 
-    sig::Type type;
-    memset(&type, 0, sizeof(type));
-    type.primitive = sig::object_P;
-    type.name = class_getName(value);
-    return CYMakeType(context, &type);
+    sig::Object type(class_getName(value));
+    return CYMakeType(context, type);
 } CYCatch(NULL) return /*XXX*/ NULL; }
 
 static JSValueRef Selector_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -2785,8 +2766,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_P);
-    Selector_type = new(pool) Type_privateData(sig::selector_P);
+    Object_type = new(pool) Type_privateData(sig::Object());
+    Selector_type = new(pool) Type_privateData(sig::Selector());
 
     NSArray_ = objc_getClass("NSArray");
     NSBlock_ = objc_getClass("NSBlock");
@@ -3032,9 +3013,9 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry {
     JSObjectRef cache(CYGetCachedObject(context, CYJSString("cache")));
     CYSetProperty(context, cache, CYJSString("YES"), JSValueMakeBoolean(context, true), kJSPropertyAttributeDontEnum);
     CYSetProperty(context, cache, CYJSString("NO"), JSValueMakeBoolean(context, false), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("id"), CYMakeType(context, sig::object_P), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("Class"), CYMakeType(context, sig::typename_P), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("SEL"), CYMakeType(context, sig::selector_P), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("id"), CYMakeType(context, sig::Object()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("Class"), CYMakeType(context, sig::Meta()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("SEL"), CYMakeType(context, sig::Selector()), kJSPropertyAttributeDontEnum);
 } CYPoolCatch() }
 
 static void *CYObjectiveC_CastSymbol(const char *name) {
@@ -3052,8 +3033,6 @@ static CYHook CYObjectiveCHook = {
     &CYObjectiveC_CallFunction,
     &CYObjectiveC_Initialize,
     &CYObjectiveC_SetupContext,
-    &CYObjectiveC_PoolFFI,
-    &CYObjectiveC_FromFFI,
     &CYObjectiveC_CastSymbol,
 };
 
index e7b1b2ca8fdc76d7d46317d0ce18544cf35b71ce..dc5782a2491af1fc0989e59eeef9cd3456a756e5 100644 (file)
@@ -1013,20 +1013,30 @@ void Try::Output(CYOutput &out, CYFlags flags) const {
 
 } }
 
-void CYTypeError::Output(CYOutput &out) const {
-    out << "@error";
-}
+void CYTypeCharacter::Output(CYOutput &out) const {
+    switch (signing_) {
+        case CYTypeNeutral: break;
+        case CYTypeSigned: out << "signed" << ' '; break;
+        case CYTypeUnsigned: out << "unsigned" << ' '; break;
+    }
 
-void CYTypeLong::Output(CYOutput &out) const {
-    out << "long" << specifier_;
+    out << "char";
 }
 
-void CYTypeShort::Output(CYOutput &out) const {
-    out << "short" << specifier_;
+void CYTypeError::Output(CYOutput &out) const {
+    out << "@error";
 }
 
-void CYTypeSigned::Output(CYOutput &out) const {
-    out << "signed" << specifier_;
+void CYTypeIntegral::Output(CYOutput &out) const {
+    if (signing_ == CYTypeUnsigned)
+        out << "unsigned" << ' ';
+    switch (length_) {
+        case 0: out << "short"; break;
+        case 1: out << "int"; break;
+        case 2: out << "long"; break;
+        case 3: out << "long" << ' ' << "long"; break;
+        default: _assert(false);
+    }
 }
 
 void CYTypeStruct::Output(CYOutput &out) const {
@@ -1037,10 +1047,6 @@ void CYTypeStruct::Output(CYOutput &out) const {
         out << *tail_;
 }
 
-void CYTypeUnsigned::Output(CYOutput &out) const {
-    out << "unsigned" << specifier_;
-}
-
 void CYTypeReference::Output(CYOutput &out) const {
     out << "struct" << ' ' << *name_;
 }
index ac4237301acdac380f886f6c829b79e760304e96..2a1bf22e61aa7f5d99cabbd9375a1ae2f567f78d 100644 (file)
@@ -81,6 +81,7 @@
 %union { CYWord *word_; }
 
 @begin C
+%union { CYTypeIntegral *integral_; }
 %union { CYTypeStructField *structField_; }
 %union { CYTypeModifier *modifier_; }
 %union { CYTypeSpecifier *specifier_; }
@@ -653,8 +654,8 @@ type; })
 %type <expression_> YieldExpression
 
 @begin C
-%type <specifier_> IntegerType
-%type <specifier_> IntegerTypeOpt
+%type <integral_> IntegerType
+%type <integral_> IntegerTypeOpt
 %type <typedIdentifier_> PrefixedType
 %type <specifier_> PrimitiveType
 %type <structField_> StructFieldListOpt
@@ -2059,16 +2060,16 @@ TypeQualifierRightOpt
     ;
 
 IntegerType
-    : "int" { $$ = CYNew CYTypeVariable("int"); }
-    | "unsigned" IntegerTypeOpt[specifier] { $$ = CYNew CYTypeUnsigned($specifier); }
-    | "signed" IntegerTypeOpt[specifier] { $$ = CYNew CYTypeSigned($specifier); }
-    | "long" IntegerTypeOpt[specifier] { $$ = CYNew CYTypeLong($specifier); }
-    | "short" IntegerTypeOpt[specifier] { $$ = CYNew CYTypeShort($specifier); }
+    : "int" { $$ = CYNew CYTypeIntegral(CYTypeNeutral); }
+    | "unsigned" IntegerTypeOpt[integral] { $$ = $integral->Unsigned(); if ($$ == NULL) CYERR(@1, "incompatible unsigned"); }
+    | "signed" IntegerTypeOpt[integral] { $$ = $integral->Signed(); if ($$ == NULL) CYERR(@1, "incompatible signed"); }
+    | "long" IntegerTypeOpt[integral] { $$ = $integral->Long(); if ($$ == NULL) CYERR(@1, "incompatible long"); }
+    | "short" IntegerTypeOpt[integral] { $$ = $integral->Short(); if ($$ == NULL) CYERR(@1, "incompatible short"); }
     ;
 
 IntegerTypeOpt
     : IntegerType[pass] { $$ = $pass; }
-    | { $$ = CYNew CYTypeVariable("int"); }
+    | { $$ = CYNew CYTypeIntegral(CYTypeNeutral); }
     ;
 
 StructFieldListOpt
@@ -2079,9 +2080,9 @@ StructFieldListOpt
 PrimitiveType
     : IdentifierType[name] { $$ = CYNew CYTypeVariable($name); }
     | IntegerType[pass] { $$ = $pass; }
-    | "char" { $$ = CYNew CYTypeVariable("char"); }
-    | "signed" "char" { $$ = CYNew CYTypeSigned(CYNew CYTypeVariable("char")); }
-    | "unsigned" "char" { $$ = CYNew CYTypeUnsigned(CYNew CYTypeVariable("char")); }
+    | "char" { $$ = CYNew CYTypeCharacter(CYTypeNeutral); }
+    | "signed" "char" { $$ = CYNew CYTypeCharacter(CYTypeSigned); }
+    | "unsigned" "char" { $$ = CYNew CYTypeCharacter(CYTypeUnsigned); }
     | "struct" IdentifierType[name] { $$ = CYNew CYTypeReference($name); }
     ;
 
index 1ae2ef0afccb4c63341a900be7a5b0f9cfdeabde..1513c8d29d410308f67ffa38458e0f8b166ccb21 100644 (file)
@@ -1191,6 +1191,15 @@ CYTarget *CYTypeBlockWith::Replace_(CYContext &context, CYTarget *type) {
     return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("blockWith")), parameters_->Argument(context)));
 }
 
+CYTarget *CYTypeCharacter::Replace(CYContext &context) {
+    switch (signing_) {
+        case CYTypeNeutral: return $V("char");
+        case CYTypeSigned: return $V("schar");
+        case CYTypeUnsigned: return $V("uchar");
+        default: _assert(false);
+    }
+}
+
 CYTarget *CYTypeConstant::Replace_(CYContext &context, CYTarget *type) {
     return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("constant"))));
 }
@@ -1210,6 +1219,17 @@ CYTarget *CYTypeExpression::Replace(CYContext &context) {
     return typed_->Replace(context);
 }
 
+CYTarget *CYTypeIntegral::Replace(CYContext &context) {
+    bool u(signing_ == CYTypeUnsigned);
+    switch (length_) {
+        case 0: return $V(u ? "ushort" : "short");
+        case 1: return $V(u ? "uint" : "int");
+        case 2: return $V(u ? "ulong" : "long");
+        case 3: return $V(u ? "ulonglong" : "longlong");
+        default: _assert(false);
+    }
+}
+
 CYTarget *CYTypeModifier::Replace(CYContext &context, CYTarget *type) { $T(type)
     return Replace_(context, type);
 }
@@ -1218,10 +1238,6 @@ CYTarget *CYTypeFunctionWith::Replace_(CYContext &context, CYTarget *type) {
     return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("functionWith")), parameters_->Argument(context)));
 }
 
-CYTarget *CYTypeLong::Replace(CYContext &context) {
-    return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("long")));
-}
-
 CYTarget *CYTypePointerTo::Replace_(CYContext &context, CYTarget *type) {
     return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("pointerTo"))));
 }
@@ -1230,14 +1246,6 @@ CYTarget *CYTypeReference::Replace(CYContext &context) {
     return $V($pool.strcat(name_->Word(), "$cy", NULL));
 }
 
-CYTarget *CYTypeShort::Replace(CYContext &context) {
-    return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("short")));
-}
-
-CYTarget *CYTypeSigned::Replace(CYContext &context) {
-    return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("signed")));
-}
-
 CYTarget *CYTypeStruct::Replace(CYContext &context) {
     CYTarget *target(tail_->Replace(context));
     if (name_ != NULL)
@@ -1245,10 +1253,6 @@ CYTarget *CYTypeStruct::Replace(CYContext &context) {
     return target;
 }
 
-CYTarget *CYTypeUnsigned::Replace(CYContext &context) {
-    return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("unsigned")));
-}
-
 CYTarget *CYTypeVariable::Replace(CYContext &context) {
     return $V(name_);
 }
index a82ded1d271a3de5b8ab96a60859be7195e00441..5599f7e27795d9d246b043e13b0b86e2f16e4584 100644 (file)
@@ -1963,23 +1963,19 @@ struct CYTypeError :
     virtual void Output(CYOutput &out) const;
 };
 
-struct CYTypeVoid :
-    CYTypeSpecifier
-{
-    CYTypeVoid() {
-    }
-
-    virtual CYTarget *Replace(CYContext &context);
-    virtual void Output(CYOutput &out) const;
+enum CYTypeSigning {
+    CYTypeNeutral,
+    CYTypeSigned,
+    CYTypeUnsigned,
 };
 
-struct CYTypeReference :
+struct CYTypeCharacter :
     CYTypeSpecifier
 {
-    CYIdentifier *name_;
+    CYTypeSigning signing_;
 
-    CYTypeReference(CYIdentifier *name) :
-        name_(name)
+    CYTypeCharacter(CYTypeSigning signing) :
+        signing_(signing)
     {
     }
 
@@ -1987,60 +1983,67 @@ struct CYTypeReference :
     virtual void Output(CYOutput &out) const;
 };
 
-struct CYTypeVariable :
+struct CYTypeIntegral :
     CYTypeSpecifier
 {
-    CYIdentifier *name_;
+    CYTypeSigning signing_;
+    int length_;
 
-    CYTypeVariable(CYIdentifier *name) :
-        name_(name)
+    CYTypeIntegral(CYTypeSigning signing, int length = 1) :
+        signing_(signing),
+        length_(length)
     {
     }
 
-    CYTypeVariable(const char *name) :
-        name_(new($pool) CYIdentifier(name))
-    {
+    CYTypeIntegral *Long() {
+        if (length_ != 1 && length_ != 2)
+            return NULL;
+        ++length_;
+        return this;
     }
 
-    virtual CYTarget *Replace(CYContext &context);
-    virtual void Output(CYOutput &out) const;
-};
+    CYTypeIntegral *Short() {
+        if (length_ != 1)
+            return NULL;
+        --length_;
+        return this;
+    }
 
-struct CYTypeUnsigned :
-    CYTypeSpecifier
-{
-    CYTypeSpecifier *specifier_;
+    CYTypeIntegral *Signed() {
+        if (signing_ != CYTypeNeutral)
+            return NULL;
+        signing_ = CYTypeSigned;
+        return this;
+    }
 
-    CYTypeUnsigned(CYTypeSpecifier *specifier) :
-        specifier_(specifier)
-    {
+    CYTypeIntegral *Unsigned() {
+        if (signing_ != CYTypeNeutral)
+            return NULL;
+        signing_ = CYTypeUnsigned;
+        return this;
     }
 
     virtual CYTarget *Replace(CYContext &context);
     virtual void Output(CYOutput &out) const;
 };
 
-struct CYTypeSigned :
+struct CYTypeVoid :
     CYTypeSpecifier
 {
-    CYTypeSpecifier *specifier_;
-
-    CYTypeSigned(CYTypeSpecifier *specifier) :
-        specifier_(specifier)
-    {
+    CYTypeVoid() {
     }
 
     virtual CYTarget *Replace(CYContext &context);
     virtual void Output(CYOutput &out) const;
 };
 
-struct CYTypeLong :
+struct CYTypeReference :
     CYTypeSpecifier
 {
-    CYTypeSpecifier *specifier_;
+    CYIdentifier *name_;
 
-    CYTypeLong(CYTypeSpecifier *specifier) :
-        specifier_(specifier)
+    CYTypeReference(CYIdentifier *name) :
+        name_(name)
     {
     }
 
@@ -2048,13 +2051,18 @@ struct CYTypeLong :
     virtual void Output(CYOutput &out) const;
 };
 
-struct CYTypeShort :
+struct CYTypeVariable :
     CYTypeSpecifier
 {
-    CYTypeSpecifier *specifier_;
+    CYIdentifier *name_;
 
-    CYTypeShort(CYTypeSpecifier *specifier) :
-        specifier_(specifier)
+    CYTypeVariable(CYIdentifier *name) :
+        name_(name)
+    {
+    }
+
+    CYTypeVariable(const char *name) :
+        name_(new($pool) CYIdentifier(name))
     {
     }
 
index 948a0f04956dc0e18bb68c81b0d11dac2a705fc7..8b43fc1187664a17162010b45b41b7621f3864a6 100644 (file)
 #include "Pooling.hpp"
 #include "sig/parse.hpp"
 
-#ifdef HAVE_FFI_FFI_H
-#include <ffi/ffi.h>
-#else
-#include <ffi.h>
-#endif
-
 namespace sig {
 
 void Copy(CYPool &pool, Element &lhs, const Element &rhs) {
     lhs.name = pool.strdup(rhs.name);
     if (rhs.type == NULL)
         lhs.type = NULL;
-    else {
-        lhs.type = new(pool) Type;
-        Copy(pool, *lhs.type, *rhs.type);
-    }
+    else
+        lhs.type = rhs.type->Copy(pool);
     lhs.offset = rhs.offset;
 }
 
@@ -53,26 +45,61 @@ void Copy(CYPool &pool, Signature &lhs, const Signature &rhs) {
         Copy(pool, lhs.elements[index], rhs.elements[index]);
 }
 
-void Copy(CYPool &pool, Type &lhs, const Type &rhs) {
-    lhs.primitive = rhs.primitive;
-    lhs.name = pool.strdup(rhs.name);
-    lhs.flags = rhs.flags;
+Void *Void::Copy(CYPool &pool, const char *name) const {
+    return new(pool) Void();
+}
 
-    if (sig::IsFunctional(rhs.primitive) || sig::IsAggregate(rhs.primitive))
-        Copy(pool, lhs.data.signature, rhs.data.signature);
-    else {
-        sig::Type *&lht(lhs.data.data.type);
-        sig::Type *const &rht(rhs.data.data.type);
-
-        if (rht == NULL)
-            lht = NULL;
-        else {
-            lht = new(pool) Type;
-            Copy(pool, *lht, *rht);
-        }
+Unknown *Unknown::Copy(CYPool &pool, const char *name) const {
+    return new(pool) Unknown();
+}
 
-        lhs.data.data.size = rhs.data.data.size;
-    }
+String *String::Copy(CYPool &pool, const char *name) const {
+    return new(pool) String();
+}
+
+Meta *Meta::Copy(CYPool &pool, const char *name) const {
+    return new(pool) Meta();
+}
+
+Selector *Selector::Copy(CYPool &pool, const char *name) const {
+    return new(pool) Selector();
+}
+
+Bits *Bits::Copy(CYPool &pool, const char *name) const {
+    return new(pool) Bits(size);
+}
+
+Pointer *Pointer::Copy(CYPool &pool, const char *name) const {
+    return new(pool) Pointer(*type.Copy(pool));
+}
+
+Array *Array::Copy(CYPool &pool, const char *name) const {
+    return new(pool) Array(*type.Copy(pool), size);
+}
+
+Object *Object::Copy(CYPool &pool, const char *name) const {
+    Object *copy(new(pool) Object(pool.strdup(name)));
+    copy->name = name;
+    return copy;
+}
+
+Aggregate *Aggregate::Copy(CYPool &pool, const char *name) const {
+    Aggregate *copy(new(pool) Aggregate(overlap, name));
+    sig::Copy(pool, copy->signature, signature);
+    copy->name = name;
+    return copy;
+}
+
+Function *Function::Copy(CYPool &pool, const char *name) const {
+    Function *copy(new(pool) Function());
+    sig::Copy(pool, copy->signature, signature);
+    return copy;
+}
+
+Block *Block::Copy(CYPool &pool, const char *name) const {
+    Block *copy(new(pool) Block());
+    sig::Copy(pool, copy->signature, signature);
+    return copy;
 }
 
 void Copy(CYPool &pool, ffi_type &lhs, ffi_type &rhs) {
@@ -98,4 +125,16 @@ void Copy(CYPool &pool, ffi_type &lhs, ffi_type &rhs) {
     }
 }
 
+const char *Type::GetName() const {
+    return NULL;
+}
+
+const char *Object::GetName() const {
+    return name;
+}
+
+const char *Aggregate::GetName() const {
+    return name;
+}
+
 }
index b75d6066feb665ec4df18d054028c7a27192ad7e..73b3912dcc10038cb473dd30357f25f5c89c2df2 100644 (file)
@@ -31,129 +31,162 @@ namespace sig {
 
 void sig_ffi_types(
     CYPool &pool,
-    ffi_type *(*sig_ffi_type)(CYPool &, struct Type *),
-    struct Signature *signature,
+    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] = (*sig_ffi_type)(pool, signature->elements[index].type);
-}
-
-ffi_type *ObjectiveC(CYPool &pool, struct Type *type) {
-    switch (type->primitive) {
-        case typename_P: return &ffi_type_pointer;
-
-        case union_P:
-            /* XXX: we can totally make this work */
-            _assert(false);
-        break;
-
-        case string_P: return &ffi_type_pointer;
-        case selector_P: return &ffi_type_pointer;
-        case block_P: return &ffi_type_pointer;
-        case object_P: return &ffi_type_pointer;
-        case boolean_P: return &ffi_type_uchar;
-        case uchar_P: return &ffi_type_uchar;
-        case uint_P: return &ffi_type_uint;
-        case ulong_P: return &ffi_type_ulong;
-        case ulonglong_P: return &ffi_type_ulonglong;
-        case ushort_P: return &ffi_type_ushort;
-
-        case array_P: {
-            // XXX: this is really lame
-            ffi_type *aggregate(new(pool) ffi_type());
-            aggregate->size = 0;
-            aggregate->alignment = 0;
-            aggregate->type = FFI_TYPE_STRUCT;
-
-            ffi_type *element(ObjectiveC(pool, type->data.data.type));
-            size_t size(type->data.data.size);
-
-            aggregate->elements = new(pool) ffi_type *[size + 1];
-            for (size_t i(0); i != size; ++i)
-                aggregate->elements[i] = element;
-            aggregate->elements[size] = NULL;
-
-            return aggregate;
-        } break;
-
-        case pointer_P: return &ffi_type_pointer;
-
-        case bit_P:
-            /* XXX: we can totally make this work */
-            _assert(false);
-        break;
-
-        case schar_P: return &ffi_type_schar;
-        case double_P: return &ffi_type_double;
-        case float_P: return &ffi_type_float;
-        case int_P: return &ffi_type_sint;
-        case long_P: return &ffi_type_slong;
-        case longlong_P: return &ffi_type_slonglong;
-        case short_P: return &ffi_type_sshort;
-
-        case void_P: return &ffi_type_void;
-        case char_P: return &ffi_type_schar;
-
-        case struct_P: {
-            ffi_type *aggregate(new(pool) ffi_type());
-            aggregate->size = 0;
-            aggregate->alignment = 0;
-            aggregate->type = FFI_TYPE_STRUCT;
-
-            aggregate->elements = new(pool) ffi_type *[type->data.signature.count + 1];
-            sig_ffi_types(pool, &ObjectiveC, &type->data.signature, aggregate->elements);
-            aggregate->elements[type->data.signature.count] = NULL;
-
-            return aggregate;
-        } break;
-
-        default:
-            _assert(false);
-        break;
-    }
-}
-
-ffi_type *Java(CYPool &pool, struct Type *type) {
-    switch (type->primitive) {
-        case typename_P: return &ffi_type_pointer;
-        case union_P: _assert(false); break;
-        case string_P: return &ffi_type_pointer;
-        case selector_P: return &ffi_type_pointer;
-        case block_P: return &ffi_type_pointer;
-        case object_P: return &ffi_type_pointer;
-        case boolean_P: return &ffi_type_uchar;
-        case uchar_P: return &ffi_type_uchar;
-        case uint_P: return &ffi_type_uint;
-        case ulong_P: return &ffi_type_ulong;
-        case ulonglong_P: return &ffi_type_ulonglong;
-        case ushort_P: return &ffi_type_ushort;
-        case array_P: return &ffi_type_pointer;
-        case pointer_P: return &ffi_type_pointer;
-        case bit_P: _assert(false); break;
-        case schar_P: return &ffi_type_schar;
-        case double_P: return &ffi_type_double;
-        case float_P: return &ffi_type_double;
-        case int_P: return &ffi_type_sint;
-        case long_P: return &ffi_type_slong;
-        case longlong_P: return &ffi_type_slonglong;
-        case short_P: return &ffi_type_sshort;
-        case void_P: return &ffi_type_void;
-        case char_P: return &ffi_type_schar;
-        case struct_P: return &ffi_type_pointer;
-
-        default:
-            _assert(false);
-        break;
-    }
+        types[index - skip + offset] = signature->elements[index].type->GetFFI(pool);
+}
+
+template <>
+ffi_type *Primitive<bool>::GetFFI(CYPool &pool) const {
+    return &ffi_type_uchar;
+}
+
+template <>
+ffi_type *Primitive<char>::GetFFI(CYPool &pool) const {
+    return &ffi_type_schar;
+}
+
+template <>
+ffi_type *Primitive<float>::GetFFI(CYPool &pool) const {
+    return &ffi_type_float;
+}
+
+template <>
+ffi_type *Primitive<double>::GetFFI(CYPool &pool) const {
+    return &ffi_type_double;
+}
+
+template <>
+ffi_type *Primitive<signed char>::GetFFI(CYPool &pool) const {
+    return &ffi_type_schar;
+}
+
+template <>
+ffi_type *Primitive<signed int>::GetFFI(CYPool &pool) const {
+    return &ffi_type_sint;
+}
+
+template <>
+ffi_type *Primitive<signed long int>::GetFFI(CYPool &pool) const {
+    return &ffi_type_slong;
+}
+
+template <>
+ffi_type *Primitive<signed long long int>::GetFFI(CYPool &pool) const {
+    return &ffi_type_slonglong;
+}
+
+template <>
+ffi_type *Primitive<signed short int>::GetFFI(CYPool &pool) const {
+    return &ffi_type_sshort;
+}
+
+template <>
+ffi_type *Primitive<unsigned char>::GetFFI(CYPool &pool) const {
+    return &ffi_type_uchar;
+}
+
+template <>
+ffi_type *Primitive<unsigned int>::GetFFI(CYPool &pool) const {
+    return &ffi_type_uint;
+}
+
+template <>
+ffi_type *Primitive<unsigned long int>::GetFFI(CYPool &pool) const {
+    return &ffi_type_ulong;
+}
+
+template <>
+ffi_type *Primitive<unsigned long long int>::GetFFI(CYPool &pool) const {
+    return &ffi_type_ulonglong;
+}
+
+template <>
+ffi_type *Primitive<unsigned short int>::GetFFI(CYPool &pool) const {
+    return &ffi_type_ushort;
+}
+
+ffi_type *Void::GetFFI(CYPool &pool) const {
+    return &ffi_type_void;
+}
+
+ffi_type *Unknown::GetFFI(CYPool &pool) const {
+    _assert(false);
+}
+
+ffi_type *String::GetFFI(CYPool &pool) const {
+    return &ffi_type_pointer;
+}
+
+ffi_type *Meta::GetFFI(CYPool &pool) const {
+    return &ffi_type_pointer;
+}
+
+ffi_type *Selector::GetFFI(CYPool &pool) const {
+    return &ffi_type_pointer;
+}
+
+ffi_type *Bits::GetFFI(CYPool &pool) const {
+    /* XXX: we can totally make this work */
+    _assert(false);
+}
+
+ffi_type *Pointer::GetFFI(CYPool &pool) const {
+    return &ffi_type_pointer;
+}
+
+ffi_type *Array::GetFFI(CYPool &pool) const {
+    // XXX: this is really lame
+    ffi_type *ffi(new(pool) ffi_type());
+    ffi->size = 0;
+    ffi->alignment = 0;
+    ffi->type = FFI_TYPE_STRUCT;
+
+    ffi_type *element(type.GetFFI(pool));
+
+    ffi->elements = new(pool) ffi_type *[size + 1];
+    for (size_t i(0); i != size; ++i)
+        ffi->elements[i] = element;
+    ffi->elements[size] = NULL;
+
+    return ffi;
+}
+
+ffi_type *Object::GetFFI(CYPool &pool) const {
+    return &ffi_type_pointer;
+}
+
+ffi_type *Aggregate::GetFFI(CYPool &pool) const {
+    // XXX: we can totally make overlap work
+    _assert(!overlap);
+
+    ffi_type *ffi(new(pool) ffi_type());
+    ffi->size = 0;
+    ffi->alignment = 0;
+    ffi->type = FFI_TYPE_STRUCT;
+
+    ffi->elements = new(pool) ffi_type *[signature.count + 1];
+    sig_ffi_types(pool, &signature, ffi->elements);
+    ffi->elements[signature.count] = NULL;
+
+    return ffi;
+}
+
+ffi_type *Function::GetFFI(CYPool &pool) const {
+    _assert(false);
+}
+
+ffi_type *Block::GetFFI(CYPool &pool) const {
+    return &ffi_type_pointer;
 }
 
 void sig_ffi_cif(
     CYPool &pool,
-    ffi_type *(*sig_ffi_type)(CYPool &, struct Type *),
     struct Signature *signature,
     ffi_cif *cif,
     size_t skip,
@@ -162,8 +195,8 @@ void sig_ffi_cif(
 ) {
     if (types == NULL)
         types = new(pool) ffi_type *[signature->count - 1];
-    ffi_type *type = (*sig_ffi_type)(pool, signature->elements[0].type);
-    sig_ffi_types(pool, sig_ffi_type, signature, types, 1 + skip, offset);
+    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);
     _assert(status == FFI_OK);
 }
index fe30373ed0a52369b7c04f0cb361c50852b5d760..b654e0f776cea6af9ccc1ea1bcbd0f1600038049 100644 (file)
 #ifndef SIG_FFI_TYPE_H
 #define SIG_FFI_TYPE_H
 
-#ifdef HAVE_FFI_FFI_H
-#include <ffi/ffi.h>
-#else
-#include <ffi.h>
-#endif
-
 #include "Pooling.hpp"
 #include "sig/types.hpp"
 
 namespace sig {
 
-ffi_type *ObjectiveC(CYPool &pool, struct Type *type);
-ffi_type *Java(CYPool &pool, struct Type *type);
-
 void sig_ffi_cif(
     CYPool &pool,
-    ffi_type *(*sig_ffi_type)(CYPool &, struct Type *),
     struct Signature *signature,
     ffi_cif *cif,
     size_t skip = 0,
index 67a28bf633fc0ab6fd5e1d481d5269b53cec1a05..e77da79bdc04053c6ad6f8347fc3dcdf98a327a4 100644 (file)
@@ -82,144 +82,145 @@ void Parse_(CYPool &pool, struct Signature *signature, const char **name, char e
     }
 }
 
-Type *Parse_(CYPool &pool, const char **name, char eos, bool named, Callback callback) {
-    char next = *(*name)++;
+Type *Parse_(CYPool &pool, const char **encoding, char eos, bool named, Callback callback) {
+    char next = *(*encoding)++;
 
-    Type *type(new(pool) Type());
-    _assert(type != NULL);
-    memset(type, 0, sizeof(Type));
+    Type *type;
+    uint8_t flags(0);
 
   parse:
     switch (next) {
-        case '?': type->primitive = unknown_P; break;
-        case '#': type->primitive = typename_P; break;
+        case '?': type = new(pool) Unknown(); break;
+        case '#': type = new(pool) Meta(); break;
 
         case '(':
-            if (type->data.signature.count < 2)
-                type->primitive = struct_P;
-            else
-                type->primitive = union_P;
+            type = new(pool) Aggregate(true);
             next = ')';
         goto aggregate;
 
-        case '*': type->primitive = string_P; break;
-        case ':': type->primitive = selector_P; break;
+        case '*': type = new(pool) String(); break;
+        case ':': type = new(pool) Selector(); break;
 
         case '@': {
-            char next(**name);
+            char next(**encoding);
 
             if (next == '?') {
-                type->primitive = block_P;
-                ++*name;
+                type = new(pool) Block();
+                ++*encoding;
             } else {
-                type->primitive = object_P;
-
-                if (next == '"') {
-                    const char *quote = strchr(*name + 1, '"');
+                const char *name;
+                if (next != '"')
+                    name = NULL;
+                else {
+                    const char *quote = strchr(*encoding + 1, '"');
                     if (quote == NULL) {
-                        printf("unterminated specific id type {%s}\n", *name - 10);
+                        printf("unterminated specific id type {%s}\n", *encoding - 10);
                         _assert(false);
                     } else if (!named || quote[1] == eos || quote[1] == '"') {
-                        type->name = pool.strmemdup(*name + 1, quote - *name - 1);
-                        *name = quote + 1;
+                        name = pool.strmemdup(*encoding + 1, quote - *encoding - 1);
+                        *encoding = quote + 1;
+                    } else {
+                        name = NULL;
                     }
                 }
+
+                type = new(pool) Object(name);
             }
 
         } break;
 
-        case 'B': type->primitive = boolean_P; break;
-        case 'C': type->primitive = uchar_P; break;
-        case 'I': type->primitive = uint_P; break;
-        case 'L': type->primitive = ulong_P; break;
-        case 'Q': type->primitive = ulonglong_P; break;
-        case 'S': type->primitive = ushort_P; break;
-
-        case '[':
-            type->primitive = array_P;
-            type->data.data.size = strtoul(*name, (char **) name, 10);
-            type->data.data.type = Parse_(pool, name, eos, false, callback);
-            if (**name != ']') {
-                printf("']' != \"%s\"\n", *name);
+        case 'B': type = new(pool) Primitive<bool>(); break;
+        case 'C': type = new(pool) Primitive<unsigned char>(); break;
+        case 'I': type = new(pool) Primitive<unsigned int>(); break;
+        case 'L': type = new(pool) Primitive<unsigned long>(); break;
+        case 'Q': type = new(pool) Primitive<unsigned long long>(); break;
+        case 'S': type = new(pool) Primitive<unsigned short>(); break;
+
+        case '[': {
+            size_t size(strtoul(*encoding, (char **) encoding, 10));
+            type = new(pool) Array(*Parse_(pool, encoding, eos, false, callback), size);
+            if (**encoding != ']') {
+                printf("']' != \"%s\"\n", *encoding);
                 _assert(false);
             }
-            ++*name;
-        break;
+            ++*encoding;
+        break;
 
         case '^':
-            type->primitive = pointer_P;
-            if (**name == '"')
-                // XXX: why is this here?
-                type->data.data.type = NULL;
-            else
-                type->data.data.type = Parse_(pool, name, eos, named, callback);
+            if (**encoding == '"')
+                _assert(false); // XXX: why is this here?!?
+            else {
+                type = Parse_(pool, encoding, eos, named, callback);
+                Aggregate *aggregate(dynamic_cast<Aggregate *>(type));
+                if (aggregate != NULL && strcmp(aggregate->name, "_objc_class") == 0)
+                    type = new(pool) Meta();
+                else
+                    type = new(pool) Pointer(*type);
+            }
         break;
 
         case 'b':
-            type->primitive = bit_P;
-            type->data.data.size = strtoul(*name, (char **) name, 10);
+            type = new(pool) Bits(strtoul(*encoding, (char **) encoding, 10));
         break;
 
-        case 'c': type->primitive = schar_P; break;
-        case 'd': type->primitive = double_P; break;
-        case 'f': type->primitive = float_P; break;
-        case 'i': type->primitive = int_P; break;
-        case 'l': type->primitive = long_P; break;
-        case 'q': type->primitive = longlong_P; break;
-        case 's': type->primitive = short_P; break;
-        case 'v': type->primitive = void_P; break;
-
-#ifdef __LP64__
-        case 'F': type->primitive = double_P; break;
-#else
-        case 'F': type->primitive = float_P; break;
-#endif
+        case 'c': type = new(pool) Primitive<signed char>(); break;
+        case 'd': type = new(pool) Primitive<double>(); break;
+        case 'f': type = new(pool) Primitive<float>(); break;
+        case 'i': type = new(pool) Primitive<signed int>(); break;
+        case 'l': type = new(pool) Primitive<signed long>(); break;
+        case 'q': type = new(pool) Primitive<signed long long>(); break;
+        case 's': type = new(pool) Primitive<short>(); break;
+        case 'v': type = new(pool) Void(); break;
 
         case '{':
-            type->primitive = struct_P;
+            type = new(pool) Aggregate(false);
             next = '}';
         goto aggregate;
 
         aggregate: {
+            Aggregate *aggregate(static_cast<Aggregate *>(type));
+
             char end = next;
-            const char *begin = *name;
-            do next = *(*name)++;
+            const char *begin = *encoding;
+            do next = *(*encoding)++;
             while (
                 next != '=' &&
                 next != '}'
             );
-            size_t length = *name - begin - 1;
+            size_t length = *encoding - begin - 1;
             if (strncmp(begin, "?", length) != 0)
-                type->name = (char *) pool.strmemdup(begin, length);
-            else
-                type->name = NULL;
-
-            // XXX: this types thing is a throwback to JocStrap
+                aggregate->name = (char *) pool.strmemdup(begin, length);
 
             if (next == '=')
-                Parse_(pool, &type->data.signature, name, end, callback);
+                Parse_(pool, &aggregate->signature, encoding, end, callback);
+
+            // XXX: this is a hack to support trivial unions
+            if (aggregate->signature.count <= 1)
+                aggregate->overlap = false;
+
+            if (callback != NULL)
+                type = (*callback)(pool, aggregate);
         } break;
 
-        case 'N': type->flags |= JOC_TYPE_INOUT; goto next;
-        case 'n': type->flags |= JOC_TYPE_IN; goto next;
-        case 'O': type->flags |= JOC_TYPE_BYCOPY; goto next;
-        case 'o': type->flags |= JOC_TYPE_OUT; goto next;
-        case 'R': type->flags |= JOC_TYPE_BYREF; goto next;
-        case 'r': type->flags |= JOC_TYPE_CONST; goto next;
-        case 'V': type->flags |= JOC_TYPE_ONEWAY; goto next;
+        case 'N': flags |= JOC_TYPE_INOUT; goto next;
+        case 'n': flags |= JOC_TYPE_IN; goto next;
+        case 'O': flags |= JOC_TYPE_BYCOPY; goto next;
+        case 'o': flags |= JOC_TYPE_OUT; goto next;
+        case 'R': flags |= JOC_TYPE_BYREF; goto next;
+        case 'r': flags |= JOC_TYPE_CONST; goto next;
+        case 'V': flags |= JOC_TYPE_ONEWAY; goto next;
 
         next:
-            next = *(*name)++;
+            next = *(*encoding)++;
             goto parse;
         break;
 
         default:
-            printf("invalid type character: '%c' {%s}\n", next, *name - 10);
+            printf("invalid type character: '%c' {%s}\n", next, *encoding - 10);
             _assert(false);
     }
 
-    if (callback != NULL)
-        (*callback)(pool, type);
+    type->flags = flags;
 
     return type;
 }
@@ -230,7 +231,7 @@ void Parse(CYPool &pool, struct Signature *signature, const char *name, Callback
     _assert(temp[-1] == '\0');
 }
 
-const char *Unparse(CYPool &pool, struct Signature *signature) {
+const char *Unparse(CYPool &pool, const struct Signature *signature) {
     const char *value = "";
     size_t offset;
 
@@ -242,71 +243,126 @@ const char *Unparse(CYPool &pool, struct Signature *signature) {
     return value;
 }
 
-const char *Unparse_(CYPool &pool, struct Type *type) {
-    switch (type->primitive) {
-        case function_P: {
-            if (type->data.signature.count == 0)
-                return "?";
-            std::ostringstream out;
-            for (size_t i(0); i != type->data.signature.count; ++i) {
-                Element &element(type->data.signature.elements[i]);
-                out << Unparse(pool, element.type);
-                if (element.offset != _not(size_t))
-                    out << pool.itoa(element.offset);
-            }
-            return pool.strdup(out.str().c_str());
-        } break;
+template <>
+const char *Primitive<bool>::Encode(CYPool &pool) const {
+    return "B";
+}
 
-        case unknown_P: return "?";
-        case typename_P: return "#";
-        case union_P: return pool.strcat("(", Unparse(pool, &type->data.signature), ")", NULL);
-        case string_P: return "*";
-        case selector_P: return ":";
-        case block_P: return "@?";
-        case object_P: return type->name == NULL ? "@" : pool.strcat("@\"", type->name, "\"", NULL);
-        case boolean_P: return "B";
-        case uchar_P: return "C";
-        case uint_P: return "I";
-        case ulong_P: return "L";
-        case ulonglong_P: return "Q";
-        case ushort_P: return "S";
-
-        case array_P: {
-            const char *value = Unparse(pool, type->data.data.type);
-            return pool.strcat("[", pool.itoa(type->data.data.size), value, "]", NULL);
-        } break;
+template <>
+const char *Primitive<char>::Encode(CYPool &pool) const {
+    return "c";
+}
 
-        case pointer_P: {
-            // XXX: protect against the weird '"' check in Parse_
-            _assert(type->data.data.type != NULL);
-            if (type->data.data.type->primitive == function_P)
-                return "^?";
-            else
-                return pool.strcat("^", Unparse(pool, type->data.data.type), NULL);
-        } break;
+template <>
+const char *Primitive<double>::Encode(CYPool &pool) const {
+    return "d";
+}
 
-        case bit_P: return pool.strcat("b", pool.itoa(type->data.data.size), NULL);
-        case schar_P: return "c";
-        case double_P: return "d";
-        case float_P: return "f";
-        case int_P: return "i";
-        case long_P: return "l";
-        case longlong_P: return "q";
-        case short_P: return "s";
-        case void_P: return "v";
-        case char_P: return "c";
-        case struct_P: return pool.strcat("{", type->name == NULL ? "?" : type->name, "=", Unparse(pool, &type->data.signature), "}", NULL);
-    }
+template <>
+const char *Primitive<float>::Encode(CYPool &pool) const {
+    return "f";
+}
+
+template <>
+const char *Primitive<signed char>::Encode(CYPool &pool) const {
+    return "c";
+}
+
+template <>
+const char *Primitive<signed int>::Encode(CYPool &pool) const {
+    return "i";
+}
+
+template <>
+const char *Primitive<signed long int>::Encode(CYPool &pool) const {
+    return "l";
+}
+
+template <>
+const char *Primitive<signed long long int>::Encode(CYPool &pool) const {
+    return "q";
+}
+
+template <>
+const char *Primitive<signed short int>::Encode(CYPool &pool) const {
+    return "s";
+}
+
+template <>
+const char *Primitive<unsigned char>::Encode(CYPool &pool) const {
+    return "C";
+}
+
+template <>
+const char *Primitive<unsigned int>::Encode(CYPool &pool) const {
+    return "I";
+}
+
+template <>
+const char *Primitive<unsigned long int>::Encode(CYPool &pool) const {
+    return "L";
+}
+
+template <>
+const char *Primitive<unsigned long long int>::Encode(CYPool &pool) const {
+    return "Q";
+}
+
+template <>
+const char *Primitive<unsigned short int>::Encode(CYPool &pool) const {
+    return "S";
+}
+
+const char *Void::Encode(CYPool &pool) const {
+    return "v";
+}
+
+const char *Unknown::Encode(CYPool &pool) const {
+    return "?";
+}
+
+const char *String::Encode(CYPool &pool) const {
+    return "*";
+}
 
-    _assert(false);
-    return NULL;
+const char *Meta::Encode(CYPool &pool) const {
+    return "#";
 }
 
-const char *Unparse(CYPool &pool, struct Type *type) {
-    if (type == NULL)
-        return "?";
+const char *Selector::Encode(CYPool &pool) const {
+    return ":";
+}
+
+const char *Bits::Encode(CYPool &pool) const {
+    return pool.strcat("b", pool.itoa(size), NULL);
+}
+
+const char *Pointer::Encode(CYPool &pool) const {
+    return pool.strcat("^", type.Encode(pool), NULL);
+}
+
+const char *Array::Encode(CYPool &pool) const {
+    return pool.strcat("[", pool.itoa(size), type.Encode(pool), "]", NULL);
+}
+
+const char *Object::Encode(CYPool &pool) const {
+    return name == NULL ? "@" : pool.strcat("@\"", name, "\"", NULL);
+}
+
+const char *Aggregate::Encode(CYPool &pool) const {
+    return pool.strcat(overlap ? "(" : "{", name == NULL ? "?" : name, "=", Unparse(pool, &signature), overlap ? ")" : "}", NULL);
+}
+
+const char *Function::Encode(CYPool &pool) const {
+    return "?";
+}
+
+const char *Block::Encode(CYPool &pool) const {
+    return "@?";
+}
 
-    const char *base(Unparse_(pool, type));
+const char *Unparse(CYPool &pool, const struct Type *type) {
+    const char *base(type->Encode(pool));
     if (type->flags == 0)
         return base;
 
index b7817c7e9eae3681332618984ecec26d54cc48d8..70428494ebc26d25bce2198ddbd36830029b3451 100644 (file)
 
 namespace sig {
 
-typedef void (*Callback)(CYPool &pool, Type *&type);
+typedef Type *(*Callback)(CYPool &pool, Aggregate *aggregate);
 void Parse(CYPool &pool, struct Signature *signature, const char *name, Callback callback);
 
-const char *Unparse(CYPool &pool, struct Signature *signature);
-const char *Unparse(CYPool &pool, struct Type *type);
+const char *Unparse(CYPool &pool, const struct Signature *signature);
+const char *Unparse(CYPool &pool, const struct Type *type);
 
-void Copy(CYPool &pool, Type &lhs, const Type &rhs);
 void Copy(CYPool &pool, Signature &lhs, const Signature &rhs);
-void Copy(CYPool &pool, Type &lhs, const Type &rhs);
 
 }
 
index 7bf83b8e579fbb26a884c24a633a6adbcded63e3..d437475091e978f8aa9c72179cfe2544f6a3c97d 100644 (file)
 #include <cstdlib>
 #include <stdint.h>
 
+#include <JavaScriptCore/JSBase.h>
+
+#ifdef HAVE_FFI_FFI_H
+#include <ffi/ffi.h>
+#else
+#include <ffi.h>
+#endif
+
 #include "Standard.hpp"
 
+class CYPool;
+struct CYTypedIdentifier;
+
 namespace sig {
 
-enum Primitive {
-    function_P = '\0',
-    block_P = '\a',
-    char_P = '\b',
-
-    unknown_P = '?',
-    typename_P = '#',
-    union_P = '(',
-    string_P = '*',
-    selector_P = ':',
-    object_P = 'W',
-    boolean_P = 'B',
-    uchar_P = 'C',
-    uint_P = 'I',
-    ulong_P = 'L',
-    ulonglong_P = 'Q',
-    ushort_P = 'S',
-    array_P = '[',
-    pointer_P = '^',
-    bit_P = 'b',
-    schar_P = 'c',
-    double_P = 'd',
-    float_P = 'f',
-    int_P = 'i',
-    long_P = 'l',
-    longlong_P = 'q',
-    short_P = 's',
-    void_P = 'v',
-    struct_P = '{'
+#define JOC_TYPE_INOUT  (1 << 0)
+#define JOC_TYPE_IN     (1 << 1)
+#define JOC_TYPE_BYCOPY (1 << 2)
+#define JOC_TYPE_OUT    (1 << 3)
+#define JOC_TYPE_BYREF  (1 << 4)
+#define JOC_TYPE_CONST  (1 << 5)
+#define JOC_TYPE_ONEWAY (1 << 6)
+
+struct Type {
+    uint8_t flags;
+
+    Type() :
+        flags(0)
+    {
+    }
+
+    virtual Type *Copy(CYPool &pool, const char *name = NULL) const = 0;
+    virtual const char *GetName() const;
+
+    virtual const char *Encode(CYPool &pool) const = 0;
+    virtual CYTypedIdentifier *Decode(CYPool &pool) const = 0;
+
+    virtual ffi_type *GetFFI(CYPool &pool) const = 0;
+    virtual void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const = 0;
+    virtual JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize = false, JSObjectRef owner = NULL) const = 0;
+
+    virtual size_t Translate(Type *&type) const {
+        return _not(size_t);
+    }
+};
+
+template <typename Type_>
+struct Primitive :
+    Type
+{
+    Primitive *Copy(CYPool &pool, const char *name) const {
+        return new(pool) Primitive();
+    }
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
 };
 
 struct Element {
     const char *name;
-    struct Type *type;
+    Type *type;
     size_t offset;
 };
 
 struct Signature {
-    struct Element *elements;
+    Element *elements;
     size_t count;
 };
 
-#define JOC_TYPE_INOUT  (1 << 0)
-#define JOC_TYPE_IN     (1 << 1)
-#define JOC_TYPE_BYCOPY (1 << 2)
-#define JOC_TYPE_OUT    (1 << 3)
-#define JOC_TYPE_BYREF  (1 << 4)
-#define JOC_TYPE_CONST  (1 << 5)
-#define JOC_TYPE_ONEWAY (1 << 6)
+struct Void :
+    Type
+{
+    Void *Copy(CYPool &pool, const char *name = NULL) const override;
 
-struct Type {
-    enum Primitive primitive;
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
+};
+
+struct Unknown :
+    Type
+{
+    Unknown *Copy(CYPool &pool, const char *name = NULL) const override;
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
+};
+
+struct String :
+    Type
+{
+    String *Copy(CYPool &pool, const char *name = NULL) const override;
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
+};
+
+struct Meta :
+    Type
+{
+    Meta *Copy(CYPool &pool, const char *name = NULL) const override;
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
+};
+
+struct Selector :
+    Type
+{
+    Selector *Copy(CYPool &pool, const char *name = NULL) const override;
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
+};
+
+struct Bits :
+    Type
+{
+    size_t size;
+
+    Bits(size_t size) :
+        size(size)
+    {
+    }
+
+    Bits *Copy(CYPool &pool, const char *name = NULL) const override;
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
+};
+
+struct Pointer :
+    Type
+{
+    Type &type;
+
+    Pointer(Type &type) :
+        type(type)
+    {
+    }
+
+    Pointer *Copy(CYPool &pool, const char *name = NULL) const override;
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
+};
+
+struct Array :
+    Type
+{
+    Type &type;
+    size_t size;
+
+    Array(Type &type, size_t size = _not(size_t)) :
+        type(type),
+        size(size)
+    {
+    }
+
+    Array *Copy(CYPool &pool, const char *name = NULL) const override;
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
+
+    size_t Translate(Type *&type) const override {
+        type = &this->type;
+        return size;
+    }
+};
+
+struct Object :
+    Type
+{
     const char *name;
-    uint8_t flags;
 
-    union {
-        struct {
-            struct Type *type;
-            size_t size;
-        } data;
+    Object(const char *name = NULL) :
+        name(name)
+    {
+    }
 
-        struct Signature signature;
-    } data;
+    Object *Copy(CYPool &pool, const char *name = NULL) const override;
+    const char *GetName() const override;
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
 };
 
-struct Type *joc_parse_type(char **name, char eos, bool variable, bool signature);
-void joc_parse_signature(struct Signature *signature, char **name, char eos, bool variable);
+struct Aggregate :
+    Type
+{
+    bool overlap;
+    const char *name;
+    Signature signature;
 
-_finline bool IsFunctional(Primitive primitive) {
-    return primitive == block_P || primitive == function_P;
-}
+    Aggregate(bool overlap, const char *name = NULL) :
+        overlap(overlap),
+        name(name)
+    {
+    }
 
-_finline bool IsAggregate(Primitive primitive) {
-    return primitive == struct_P || primitive == union_P;
-}
+    Aggregate *Copy(CYPool &pool, const char *name = NULL) const override;
+    const char *GetName() const override;
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
+};
+
+struct Callable :
+    Type
+{
+    Signature signature;
+};
+
+struct Function :
+    Callable
+{
+    Function *Copy(CYPool &pool, const char *name = NULL) const override;
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
+};
+
+struct Block :
+    Callable
+{
+    Block *Copy(CYPool &pool, const char *name = NULL) const override;
+
+    const char *Encode(CYPool &pool) const override;
+    CYTypedIdentifier *Decode(CYPool &pool) const override;
+
+    ffi_type *GetFFI(CYPool &pool) const override;
+    void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override;
+    JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override;
+};
+
+Type *joc_parse_type(char **name, char eos, bool variable, bool signature);
+void joc_parse_signature(Signature *signature, char **name, char eos, bool variable);
 
 }