Add support for Objective-C boxed expression syntax.
authorJay Freeman (saurik) <saurik@saurik.com>
Sun, 3 Jun 2012 20:45:59 +0000 (13:45 -0700)
committerJay Freeman (saurik) <saurik@saurik.com>
Sun, 3 Jun 2012 20:59:20 +0000 (13:59 -0700)
Cycript.yy.in
ObjectiveC/Library.mm
ObjectiveC/Output.mm
ObjectiveC/Replace.cpp
ObjectiveC/Syntax.hpp

index f289f76773bae1461946a4ed57664b23a1be4c35..9c05469a3445eebc81fdba7f69e07e55e6934266 100644 (file)
@@ -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
index 64281a301e9669900f56e46f05c5e78a6b10ad07..81f182be5707bda764a82ce0693bbd1c5dcefc3d 100644 (file)
@@ -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<Internal *>(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
index e406493cf4662b413ce5e587f0941976950f357e..a34826d6dca594f2487e799bf5fd1ca8881b5f1c 100644 (file)
@@ -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)
index 67a2ef602dd85411b3f2ddb91f4fb3b6cc91f701..748fc6fcbe116076184f41a5f57357081da24d9d 100644 (file)
@@ -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)->*
index a5e826de70c899a1843dca6f775fac7f3ff423dc..ec06425fabad2c847b7bc73a73a85c0d5ee9037e 100644 (file)
 
 #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<CYSelectorPart>,
     CYThing