From 3fe16be7c02b11754e3d367ffd228beb14da2555 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Fri, 17 Jan 2014 02:23:00 -0800 Subject: [PATCH] Add support to @encode, Decode_, and With blocks. --- Cycript.yy.in | 1 + Decode.cpp | 9 ++++++- Execute.cpp | 73 +++++++++++++++++++++++++++++---------------------- Output.cpp | 6 +++++ Parser.hpp | 17 ++++++++++++ Replace.cpp | 4 +++ sig/copy.cpp | 2 +- sig/types.hpp | 4 +++ 8 files changed, 82 insertions(+), 34 deletions(-) diff --git a/Cycript.yy.in b/Cycript.yy.in index 89ed1a9..e1408da 100644 --- a/Cycript.yy.in +++ b/Cycript.yy.in @@ -1391,6 +1391,7 @@ FunctionedType SuffixedType : ArrayedType { $$ = $1; } + | "(" LexPushInOff "^" TypeQualifierRight ")" LexPopIn "(" LexPushInOff TypedParameterListOpt ")" LexPopIn { $$ = $4; $$->modifier_ = CYNew CYTypeBlockWith($9, $$->modifier_); } | TypeParenthetical FunctionedType { $$ = $1; CYSetLast($2) = $$->modifier_; $$->modifier_ = $2; } | FunctionedType { $$ = CYNew CYTypedIdentifier(); CYSetLast($1) = $$->modifier_; $$->modifier_ = $1; } ; diff --git a/Decode.cpp b/Decode.cpp index f99f61f..9cb165c 100644 --- a/Decode.cpp +++ b/Decode.cpp @@ -38,7 +38,14 @@ CYTypedIdentifier *Decode_(CYPool &pool, struct sig::Type *type) { case sig::union_P: _assert(false); break; case sig::string_P: return $ CYTypedIdentifier($V("char"), $ CYTypePointerTo()); case sig::selector_P: return $ CYTypedIdentifier($V("SEL")); - case sig::block_P: _assert(false); break; + + case sig::block_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($ CYTypeBlockWith(parameter)); + } break; case sig::object_P: { if (type->name == NULL) diff --git a/Execute.cpp b/Execute.cpp index 6c26240..aff9a7e 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -1069,6 +1069,38 @@ static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t cou return CYMakeType(context, type); } 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 { + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + + CYPool pool; + + sig::Type type; + type.name = NULL; + type.flags = 0; + + 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); + + for (size_t i(0); i != count; ++i) { + sig::Element &element(type.data.signature.elements[i + 1]); + element.name = NULL; + element.offset = _not(size_t); + + JSObjectRef object(CYCastJSObject(context, arguments[i])); + _assert(JSValueIsObjectOfClass(context, object, Type_privateData::Class_)); + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); + + element.type = internal->type_; + } + + return CYMakeType(context, &type); +} CYCatch(NULL) } + static JSValueRef Type_callAsFunction_arrayOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 1) throw CYJSError(context, "incorrect number of arguments to Type.arrayOf"); @@ -1090,6 +1122,10 @@ static JSValueRef Type_callAsFunction_arrayOf(JSContextRef context, JSObjectRef 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); +} + static JSValueRef Type_callAsFunction_constant(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.constant"); @@ -1100,37 +1136,9 @@ static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef 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) { CYTry { - Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - - CYPool pool; - - sig::Type type; - type.name = NULL; - type.flags = 0; - - type.primitive = sig::function_P; - 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); - - for (size_t i(0); i != count; ++i) { - sig::Element &element(type.data.signature.elements[i + 1]); - element.name = NULL; - element.offset = _not(size_t); - - JSObjectRef object(CYCastJSObject(context, arguments[i])); - _assert(JSValueIsObjectOfClass(context, object, Type_privateData::Class_)); - Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); - - element.type = internal->type_; - } - - 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); +} static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 0) @@ -1319,8 +1327,9 @@ static JSStaticValue Type_staticValues[4] = { {NULL, NULL, NULL, 0} }; -static JSStaticFunction Type_staticFunctions[9] = { +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}, {"pointerTo", &Type_callAsFunction_pointerTo, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, diff --git a/Output.cpp b/Output.cpp index 17f7bde..51134c7 100644 --- a/Output.cpp +++ b/Output.cpp @@ -481,6 +481,12 @@ void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const { out << ']'; } +void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const { + out << '(' << '^'; + next_->Output(out, Precedence(), identifier); + out << ')' << '(' << parameters_ << ')'; +} + void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const { out << "const"; next_->Output(out, Precedence(), identifier); diff --git a/Parser.hpp b/Parser.hpp index e68cf1a..e182c57 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -1776,6 +1776,23 @@ struct CYTypeDefinition : virtual void Output(CYOutput &out, CYFlags flags) const; }; +struct CYTypeBlockWith : + CYTypeModifier +{ + CYTypedParameter *parameters_; + + CYTypeBlockWith(CYTypedParameter *parameters, CYTypeModifier *next = NULL) : + CYTypeModifier(next), + parameters_(parameters) + { + } + + CYPrecedence(0) + + virtual CYExpression *Replace_(CYContext &context, CYExpression *type); + virtual void Output(CYOutput &out, CYIdentifier *identifier) const; +}; + struct CYTypeFunctionWith : CYTypeModifier { diff --git a/Replace.cpp b/Replace.cpp index 1ddc5c1..83a5c47 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -873,6 +873,10 @@ CYExpression *CYTypeArrayOf::Replace_(CYContext &context, CYExpression *type) { return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("arrayOf")), $ CYArgument(size_))); } +CYExpression *CYTypeBlockWith::Replace_(CYContext &context, CYExpression *type) { + return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("blockWith")), parameters_->Argument(context))); +} + CYExpression *CYTypeConstant::Replace_(CYContext &context, CYExpression *type) { return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("constant")))); } diff --git a/sig/copy.cpp b/sig/copy.cpp index b2c20f5..9300a1d 100644 --- a/sig/copy.cpp +++ b/sig/copy.cpp @@ -58,7 +58,7 @@ void Copy(CYPool &pool, Type &lhs, const Type &rhs) { lhs.name = pool.strdup(rhs.name); lhs.flags = rhs.flags; - if (rhs.primitive == '\0' || sig::IsAggregate(rhs.primitive)) + 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); diff --git a/sig/types.hpp b/sig/types.hpp index e66e0c3..150a057 100644 --- a/sig/types.hpp +++ b/sig/types.hpp @@ -94,6 +94,10 @@ struct Type { 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); +_finline bool IsFunctional(Primitive primitive) { + return primitive == block_P || primitive == function_P; +} + _finline bool IsAggregate(Primitive primitive) { return primitive == struct_P || primitive == union_P; } -- 2.47.2