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