#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());
#include "Syntax.hpp"
-CYTypedIdentifier *Decode(CYPool &pool, struct sig::Type *type);
+CYTypedIdentifier *CYDecodeType(CYPool &pool, struct sig::Type *type);
#endif//DECODE_HPP
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_;
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)
}
};
-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));
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);
}
}
}
-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));
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) {
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;
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]);
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"))
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 {
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;
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;
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];
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];
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 {
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) {
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 {
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));
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);
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 {
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 {
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 {
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 {
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 {
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 {
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);
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 {
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 {
} 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 {
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 {
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) }
{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}
};
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)
#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_;
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)
{
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() {
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;
{
private:
void set() {
- sig::sig_ffi_cif(*pool_, &sig::ObjectiveC, &signature_, &cif_);
+ sig::sig_ffi_cif(*pool_, &signature_, &cif_);
}
public:
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)());
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 *);
};
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);
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;
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
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)));
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));
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)) {
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);
#endif
auto type(new(pool) Type_privateData(encoding));
- return CYFromFFI(context, type->type_, type->GetFFI(), data);
+ return type->type_->FromFFI(context, type->GetFFI(), data);
}
}
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;
}
}
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;
}
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
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 {
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 {
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");
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) {
&CYObjectiveC_CallFunction,
&CYObjectiveC_Initialize,
&CYObjectiveC_SetupContext,
- &CYObjectiveC_PoolFFI,
- &CYObjectiveC_FromFFI,
&CYObjectiveC_CastSymbol,
};
} }
-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 {
out << *tail_;
}
-void CYTypeUnsigned::Output(CYOutput &out) const {
- out << "unsigned" << specifier_;
-}
-
void CYTypeReference::Output(CYOutput &out) const {
out << "struct" << ' ' << *name_;
}
%union { CYWord *word_; }
@begin C
+%union { CYTypeIntegral *integral_; }
%union { CYTypeStructField *structField_; }
%union { CYTypeModifier *modifier_; }
%union { CYTypeSpecifier *specifier_; }
%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
;
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
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); }
;
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"))));
}
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);
}
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"))));
}
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)
return target;
}
-CYTarget *CYTypeUnsigned::Replace(CYContext &context) {
- return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("unsigned")));
-}
-
CYTarget *CYTypeVariable::Replace(CYContext &context) {
return $V(name_);
}
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)
{
}
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)
{
}
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))
{
}
#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;
}
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) {
}
}
+const char *Type::GetName() const {
+ return NULL;
+}
+
+const char *Object::GetName() const {
+ return name;
+}
+
+const char *Aggregate::GetName() const {
+ return name;
+}
+
}
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,
) {
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);
}
#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,
}
}
-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;
}
_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;
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;
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);
}
#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);
}