From f2f0d1d14705a8dc96cb6787ff1e1d170efabc90 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Sun, 3 Jun 2012 13:45:59 -0700 Subject: [PATCH] Add support for Objective-C boxed expression syntax. --- Cycript.yy.in | 8 +++++++- ObjectiveC/Library.mm | 30 ++++++++++++++++++++++++++++++ ObjectiveC/Output.mm | 5 +++++ ObjectiveC/Replace.cpp | 4 ++++ ObjectiveC/Syntax.hpp | 16 ++++++++++++++++ 5 files changed, 62 insertions(+), 1 deletion(-) diff --git a/Cycript.yy.in b/Cycript.yy.in index f289f76..9c05469 100644 --- a/Cycript.yy.in +++ b/Cycript.yy.in @@ -641,6 +641,13 @@ Word | "while" { $$ = $1; } | "with" { $$ = $1; } ; + +PrimaryExpressionNo + : "@" LiteralNoRE { $$ = CYNew CYBox($2); } + | "@" ArrayLiteral { $$ = CYNew CYBox($2); } + | "@" ObjectLiteral { $$ = CYNew CYBox($2); } + | "@" "(" Expression ")" { $$ = CYNew CYBox($3); } + ; @end Identifier @@ -687,7 +694,6 @@ LiteralNoRE | BooleanLiteral { $$ = $1; } | NumericLiteral { $$ = $1; } | StringLiteral { $$ = $1; } - | "@" StringLiteral { $$ = $2; } ; LiteralRE diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index 64281a3..81f182b 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -394,6 +394,7 @@ JSObjectRef CYMakeInstance(JSContextRef context, id object, bool transient) { @end @protocol Cycript +- (id) cy$box; - (JSValueRef) cy$JSValueInContext:(JSContextRef)context; @end @@ -679,6 +680,10 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu /* Bridge: NSArray {{{ */ @implementation NSArray (Cycript) +- (id) cy$box { + return [[self mutableCopy] autorelease]; +} + - (NSString *) cy$toCYON { NSMutableString *json([[[NSMutableString alloc] init] autorelease]); [json appendString:@"@["]; @@ -779,6 +784,10 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu /* Bridge: NSDictionary {{{ */ @implementation NSDictionary (Cycript) +- (id) cy$box { + return [[self mutableCopy] autorelease]; +} + - (NSString *) cy$toCYON { NSMutableString *json([[[NSMutableString alloc] init] autorelease]); [json appendString:@"@{"]; @@ -951,6 +960,10 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu /* Bridge: NSObject {{{ */ @implementation NSObject (Cycript) +- (id) cy$box { + return self; +} + - (JSValueRef) cy$JSValueInContext:(JSContextRef)context { CYObjectiveTry_(context) { return NULL; } CYObjectiveCatch } @@ -1012,6 +1025,10 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu /* Bridge: NSString {{{ */ @implementation NSString (Cycript) +- (id) cy$box { + return [[self copy] autorelease]; +} + - (JSType) cy$JSType { return kJSTypeString; } @@ -1821,6 +1838,16 @@ static bool Instance_hasInstance(JSContextRef context, JSObjectRef constructor, return false; } CYCatch } +static JSValueRef Instance_box_callAsFunction(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 Instance"); + CYPool pool; + id value(CYCastNSObject(pool, context, arguments[0])); + if (value == nil) + value = [NSNull null]; + return CYCastJSValue(context, [value cy$box]); +} CYCatch } + static bool Internal_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) { Internal *internal(reinterpret_cast(JSObjectGetPrivate(object))); CYPool pool; @@ -2565,6 +2592,9 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry { CYSetProperty(context, cycript, CYJSString("Selector"), Selector); CYSetProperty(context, cycript, CYJSString("Super"), Super); + JSObjectRef box(JSObjectMakeFunctionWithCallback(context, CYJSString("box"), &Instance_box_callAsFunction)); + CYSetProperty(context, Instance, CYJSString("box"), box); + #if defined(__APPLE__) && defined(__arm__) && 0 CYSetProperty(context, all, CYJSString("objc_registerClassPair"), &objc_registerClassPair_, kJSPropertyAttributeDontEnum); #endif diff --git a/ObjectiveC/Output.mm b/ObjectiveC/Output.mm index e406493..a34826d 100644 --- a/ObjectiveC/Output.mm +++ b/ObjectiveC/Output.mm @@ -95,6 +95,11 @@ void CYMessage::Output(CYOutput &out, bool replace) const { out << code_; } +void CYBox::Output(CYOutput &out, CYFlags flags) const { + out << '@'; + value_->Output(out, Precedence(), CYRight(flags)); +} + void CYProtocol::Output(CYOutput &out) const { name_->Output(out, CYAssign::Precedence_, CYNoFlags); if (next_ != NULL) diff --git a/ObjectiveC/Replace.cpp b/ObjectiveC/Replace.cpp index 67a2ef6..748fc6f 100644 --- a/ObjectiveC/Replace.cpp +++ b/ObjectiveC/Replace.cpp @@ -104,6 +104,10 @@ CYSelectorPart *CYMessageParameter::SelectorPart(CYContext &context) const { $T( return tag_ == NULL ? next : $ CYSelectorPart(tag_, name_ != NULL, next); } +CYExpression *CYBox::Replace(CYContext &context) { + return $C1($M($V("Instance"), $S("box")), value_); +} + CYStatement *CYProtocol::Replace(CYContext &context) const { $T(NULL) return $ CYBlock($$->* next_->Replace(context)->* diff --git a/ObjectiveC/Syntax.hpp b/ObjectiveC/Syntax.hpp index a5e826d..ec06425 100644 --- a/ObjectiveC/Syntax.hpp +++ b/ObjectiveC/Syntax.hpp @@ -24,6 +24,22 @@ #include "Parser.hpp" +struct CYBox : + CYExpression +{ + CYExpression *value_; + + CYBox(CYExpression *value) : + value_(value) + { + } + + CYPrecedence(1) + + virtual CYExpression *Replace(CYContext &context); + virtual void Output(CYOutput &out, CYFlags flags) const; +}; + struct CYSelectorPart : CYNext, CYThing -- 2.47.2