From: Jay Freeman (saurik) Date: Fri, 1 Jan 2016 19:14:17 +0000 (-0800) Subject: Add x.[] syntax for "legitimate" subscript access. X-Git-Tag: v0.9.590~103 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/e56c24995a0c0ffaed5b6769a2bead83ced2de03?hp=dbf05bfd2ab79568fe706daa9112037192d4d9dd Add x.[] syntax for "legitimate" subscript access. --- diff --git a/Output.cpp b/Output.cpp index e8ae4ae..987abf6 100644 --- a/Output.cpp +++ b/Output.cpp @@ -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) { diff --git a/Parser.ypp.in b/Parser.ypp.in index ffa42cc..0d48316 100644 --- a/Parser.ypp.in +++ b/Parser.ypp.in @@ -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 diff --git a/Replace.cpp b/Replace.cpp index 7a99296..1944be5 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -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(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))); } diff --git a/Syntax.hpp b/Syntax.hpp index 4a93e03..fa27dd4 100644 --- a/Syntax.hpp +++ b/Syntax.hpp @@ -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 { diff --git a/libcycript.cy b/libcycript.cy index 88fe069..578f924 100644 --- a/libcycript.cy +++ b/libcycript.cy @@ -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) {