break;
 
         CYPoolFFI_(uchar, unsigned char)
-        CYPoolFFI_(char, char)
+        CYPoolFFI_(schar, signed char)
         CYPoolFFI_(ushort, unsigned short)
         CYPoolFFI_(short, short)
         CYPoolFFI_(ulong, unsigned long)
         case sig::void_P:
         break;
 
+        // XXX: implement a conversion from a single character string?
+        CYPoolFFI_(char, char)
+
         default:
             for (CYHook *hook : GetHooks())
                 if (hook->PoolFFI != NULL)
             return CYCastJSValue(context, *reinterpret_cast<native *>(data)); \
 
         CYFromFFI_(uchar, unsigned char)
-        CYFromFFI_(char, char)
+        CYFromFFI_(schar, signed char)
         CYFromFFI_(ushort, unsigned short)
         CYFromFFI_(short, short)
         CYFromFFI_(ulong, unsigned long)
         case sig::void_P:
             return CYJSUndefined(context);
 
+        CYFromFFI_(char, char)
+
         null:
             return CYJSNull(context);
         default:
     return CYCallAsFunction(context, functor, _this, count, arguments);
 } CYCatch(NULL) }
 
-JSObjectRef CYMakeType(JSContextRef context, const char *encoding) {
-    Type_privateData *internal(new Type_privateData(encoding));
+JSObjectRef CYMakeType(JSContextRef context, sig::Primitive primitive) {
+    Type_privateData *internal(new Type_privateData(primitive));
     return JSObjectMake(context, Type_privateData::Class_, internal);
 }
 
 
     if (false) {
     } else if (count == 1) {
-        const char *type(CYPoolCString(pool, context, arguments[0]));
-        return CYMakeType(context, type);
+        const char *encoding(CYPoolCString(pool, context, arguments[0]));
+        sig::Signature signature;
+        sig::Parse(pool, &signature, encoding, &Structor_);
+        return CYMakeType(context, signature.elements[0].type);
     } else if (count == 2) {
         JSObjectRef types(CYCastJSObject(context, arguments[0]));
         size_t count(CYArrayLength(context, types));
     sig::Type type(*internal->type_);
 
     switch (type.primitive) {
-        case sig::char_P: case sig::uchar_P: type.primitive = sig::char_P; break;
+        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;
     sig::Type type(*internal->type_);
 
     switch (type.primitive) {
-        case sig::char_P: case sig::uchar_P: type.primitive = sig::uchar_P; break;
+        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;
 
     CYSetProperty(context, cache, CYJSString("NULL"), CYJSNull(context), kJSPropertyAttributeDontEnum);
 
-    CYSetProperty(context, cache, CYJSString("bool"), CYMakeType(context, "B"), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("char"), CYMakeType(context, "c"), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("short"), CYMakeType(context, "s"), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("int"), CYMakeType(context, "i"), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("long"), CYMakeType(context, "l"), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("float"), CYMakeType(context, "f"), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("double"), CYMakeType(context, "d"), 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);
 
     for (CYHook *hook : GetHooks())
         if (hook->SetupContext != NULL)
 
     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, "@"), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("Class"), CYMakeType(context, "#"), kJSPropertyAttributeDontEnum);
-    CYSetProperty(context, cache, CYJSString("SEL"), CYMakeType(context, ":"), 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);
 } CYPoolCatch() }
 
 static void *CYObjectiveC_CastSymbol(const char *name) {
 
             _assert(false);
         break;
 
-        case char_P: return &ffi_type_schar;
+        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 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());
         case array_P: return &ffi_type_pointer;
         case pointer_P: return &ffi_type_pointer;
         case bit_P: _assert(false); break;
-        case char_P: return &ffi_type_schar;
+        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 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: