]> git.saurik.com Git - cycript.git/commitdiff
Add x.[] syntax for "legitimate" subscript access.
authorJay Freeman (saurik) <saurik@saurik.com>
Fri, 1 Jan 2016 19:14:17 +0000 (11:14 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Fri, 1 Jan 2016 19:14:17 +0000 (11:14 -0800)
Output.cpp
Parser.ypp.in
Replace.cpp
Syntax.hpp
libcycript.cy

index e8ae4aeb7071890a4bf7af8f41df49759b0b1743..987abf61c8c6fc791ab878140c4aa060354daeaa 100644 (file)
@@ -890,6 +890,11 @@ void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
     out << '\t' << '}';
 }
 
+void CYSubscriptMember::Output(CYOutput &out, CYFlags flags) const {
+    object_->Output(out, Precedence(), CYLeft(flags));
+    out << "." << '[' << *property_ << ']';
+}
+
 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
     bool first(true);
     CYForEach (next, this) {
index ffa42cc32e9e114dfa2ceb562fe06f544a359d4f..0d48316a23b2ddc2ebc3599419935b49064e20fe 100644 (file)
@@ -2664,6 +2664,11 @@ ArgumentList
     : LexOf WordNoUnary[tag] ":" AssignmentExpression[value] ArgumentList_[next] { $$ = CYNew CYArgument($tag, $value, $next); }
     ;
 /* }}} */
+/* JavaScript FTW: Subscript Access {{{ */
+MemberAccess
+    : "." "[" AssignmentExpression[property] "]" { $$ = CYNew CYSubscriptMember(NULL, $property); }
+    ;
+/* }}} */
 
 /* JavaScript FTW: Java "Anonymous Inner Classes" {{{ */
 BracedParameter
index 7a99296e95849a93e026b4e524786c5908b8c373..1944be51aa4adafa8ee683b671a1b1afcd33ca23 100644 (file)
@@ -117,6 +117,9 @@ CYTarget *CYArrayComprehension::Replace(CYContext &context) {
 }
 
 CYExpression *CYAssignment::Replace(CYContext &context) {
+    // XXX: this is a horrible hack but I'm a month over schedule :(
+    if (CYSubscriptMember *subscript = dynamic_cast<CYSubscriptMember *>(lhs_))
+        return $C2($M(subscript->object_, $S("$cys")), subscript->property_, rhs_);
     context.Replace(lhs_);
     context.Replace(rhs_);
     return this;
@@ -1070,6 +1073,10 @@ void CYScope::Close(CYContext &context) {
     default:; } }
 }
 
+CYTarget *CYSubscriptMember::Replace(CYContext &context) {
+    return $C1($M(object_, $S("$cyg")), property_);
+}
+
 CYElementValue *CYSpan::Replace(CYContext &context) { $T(NULL)
     return $ CYElementValue(expression_, $ CYElementValue(string_, next_->Replace(context)));
 }
index 4a93e0320d191ec3f8d0885079261e9e48e544ed..fa27dd492bd86707e16ea73fce201bd055266eb6 100644 (file)
@@ -1485,6 +1485,20 @@ struct CYResolveMember :
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
+struct CYSubscriptMember :
+    CYMember
+{
+    CYSubscriptMember(CYExpression *object, CYExpression *property) :
+        CYMember(object, property)
+    {
+    }
+
+    CYPrecedence(1)
+
+    virtual CYTarget *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
 namespace cy {
 namespace Syntax {
 
index 88fe069ee7769faa2086ff0eeed24c4728ba99a2..578f924a5f0de96d271058186b0d05b2f879a089 100644 (file)
@@ -131,6 +131,43 @@ if ("Java" in Cycript) {
             return `new java.lang.Double(${this.value})`;
         },
     });
+
+    $cy_set(java.lang.Object.prototype, {
+        // XXX: due to lack of interface prototypes :(
+        $cyg: function(key) {
+            return this.get(key);
+        },
+
+        // XXX: due to lack of interface prototypes :(
+        $cys: function(key, value) {
+            if ("set" in this)
+                this.set(key, value);
+            else
+                this.put(key, value);
+        },
+    });
+}
+
+if ("ObjectiveC" in Cycript) {
+    $cy_set(NSArray.prototype, {
+        $cyg: function(key) {
+            return objc_msgSend(this, "objectAtIndex:", key);
+        },
+
+        $cys: function(key, value) {
+            return objc_msgSend(this, "setObject:atIndex:", value, key);
+        },
+    });
+
+    $cy_set(NSDictionary.prototype, {
+        $cyg: function(key) {
+            return objc_msgSend(this, "objectForKey:", key);
+        },
+
+        $cys: function(key, value) {
+            return objc_msgSend(this, "setObject:forKey:", value, key);
+        },
+    });
 }
 
 let IsFile = function(path) {