]> git.saurik.com Git - cycript.git/commitdiff
Fix Objective-C dictionary/array literal lowering.
authorJay Freeman (saurik) <saurik@saurik.com>
Tue, 29 Dec 2015 22:10:01 +0000 (14:10 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Tue, 29 Dec 2015 22:10:01 +0000 (14:10 -0800)
Execute.cpp
ObjectiveC/Output.cpp
ObjectiveC/Replace.cpp
ObjectiveC/Syntax.hpp
Parser.ypp.in
Replace.cpp
Syntax.hpp

index 7eb6f6505353d295e1ec23c1bc25ec60c3021fd7..ced61fcf732fc0e22f94fa67d27003584886813d 100644 (file)
@@ -749,30 +749,46 @@ void Bits::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data
     _assert(false);
 }
 
     _assert(false);
 }
 
-void Pointer::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
-    *reinterpret_cast<void **>(data) = CYCastPointer<void *>(context, value);
-}
-
-void Array::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
-    uint8_t *base(reinterpret_cast<uint8_t *>(data));
-    JSObjectRef aggregate(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
-    for (size_t index(0); index != size; ++index) {
-        ffi_type *field(ffi->elements[index]);
-
+static void CYArrayCopy(CYPool *pool, JSContextRef context, uint8_t *base, size_t length, const sig::Type &type, ffi_type *ffi, JSValueRef value, JSObjectRef object) {
+    for (size_t index(0); index != length; ++index) {
         JSValueRef rhs;
         JSValueRef rhs;
-        if (aggregate == NULL)
+        if (object == NULL)
             rhs = value;
         else {
             rhs = value;
         else {
-            rhs = CYGetProperty(context, aggregate, index);
+            rhs = CYGetProperty(context, object, index);
             if (JSValueIsUndefined(context, rhs))
                 throw CYJSError(context, "unable to extract array value");
         }
 
             if (JSValueIsUndefined(context, rhs))
                 throw CYJSError(context, "unable to extract array value");
         }
 
-        type.PoolFFI(pool, context, field, base, rhs);
-        base += field->size;
+        type.PoolFFI(pool, context, ffi, base, rhs);
+        base += ffi->size;
     }
 }
 
     }
 }
 
+void Pointer::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    bool guess(false);
+    *reinterpret_cast<void **>(data) = CYCastPointer<void *>(context, value, &guess);
+    if (!guess || pool == NULL || !JSValueIsObject(context, value))
+        return;
+    JSObjectRef object(CYCastJSObject(context, value));
+    if (CYHasProperty(context, object, length_s)) {
+        size_t length(CYArrayLength(context, object));
+        ffi_type *element(type.GetFFI(*pool));
+        size_t size(element->size * length);
+        uint8_t *base(pool->malloc<uint8_t>(size, element->alignment));
+        CYArrayCopy(pool, context, base, length, type, element, value, object);
+        *reinterpret_cast<void **>(data) = base;
+    }
+}
+
+void Array::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+    if (size == 0)
+        return;
+    uint8_t *base(reinterpret_cast<uint8_t *>(data));
+    JSObjectRef object(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
+    CYArrayCopy(pool, context, base, size, type, ffi->elements[0], value, object);
+}
+
 void Aggregate::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
     _assert(!overlap);
 
 void Aggregate::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
     _assert(!overlap);
 
index a65e3863ee57f77e05ac79ef7c873f06a2d86214..37f86b1b08dffbd332e9b52f9bb0818265ddcbb0 100644 (file)
@@ -77,6 +77,14 @@ void CYBox::Output(CYOutput &out, CYFlags flags) const {
     value_->Output(out, Precedence(), CYRight(flags));
 }
 
     value_->Output(out, Precedence(), CYRight(flags));
 }
 
+void CYObjCArray::Output(CYOutput &out, CYFlags flags) const {
+    out << '@' << '[' << elements_ << ']';
+}
+
+void CYObjCDictionary::Output(CYOutput &out, CYFlags flags) const {
+    out << '@' << '{' << '}';
+}
+
 void CYObjCBlock::Output(CYOutput &out, CYFlags flags) const {
     out << '^' << ' ' << *typed_ << ' ' << '(';
 
 void CYObjCBlock::Output(CYOutput &out, CYFlags flags) const {
     out << '^' << ' ' << *typed_ << ' ' << '(';
 
index 6dd8e5500dc16cdd5c536df9aa3550750dd9029d..ab16675476c94ef4d06641631881059cab29edd6 100644 (file)
@@ -132,6 +132,27 @@ CYTarget *CYBox::Replace(CYContext &context) {
     return $C1($M($V("Instance"), $S("box")), value_);
 }
 
     return $C1($M($V("Instance"), $S("box")), value_);
 }
 
+CYTarget *CYObjCArray::Replace(CYContext &context) {
+    size_t count(0);
+    CYForEach (element, elements_)
+        ++count;
+    return $ CYSendDirect($V("NSArray"), $C_($ CYWord("arrayWithObjects"), $ CYArray(elements_), $C_($ CYWord("count"), $D(count))));
+}
+
+CYTarget *CYObjCDictionary::Replace(CYContext &context) {
+    CYList<CYElement> keys;
+    CYList<CYElement> values;
+    size_t count(0);
+
+    CYForEach (pair, pairs_) {
+        keys->*$ CYElementValue(pair->key_);
+        values->*$ CYElementValue(pair->value_);
+        ++count;
+    }
+
+    return $ CYSendDirect($V("NSDictionary"), $C_($ CYWord("dictionaryWithObjects"), $ CYArray(values), $C_($ CYWord("forKeys"), $ CYArray(keys), $C_($ CYWord("count"), $D(count)))));
+}
+
 CYTarget *CYObjCBlock::Replace(CYContext &context) {
     return $C1($ CYTypeExpression(($ CYTypedIdentifier(*typed_))->Modify($ CYTypeBlockWith(parameters_))), $ CYFunctionExpression(NULL, parameters_->Parameters(context), code_));
 }
 CYTarget *CYObjCBlock::Replace(CYContext &context) {
     return $C1($ CYTypeExpression(($ CYTypedIdentifier(*typed_))->Modify($ CYTypeBlockWith(parameters_))), $ CYFunctionExpression(NULL, parameters_->Parameters(context), code_));
 }
index 16927ac34ca314c03e149375785cb19c7a70104d..e4b073214b060ef03cb581318eebdc1d3f962f3b 100644 (file)
@@ -76,6 +76,52 @@ struct CYBox :
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
+struct CYObjCArray :
+    CYTarget
+{
+    CYElement *elements_;
+
+    CYObjCArray(CYElement *elements = NULL) :
+        elements_(elements)
+    {
+    }
+
+    CYPrecedence(0)
+
+    virtual CYTarget *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
+struct CYObjCKeyValue :
+    CYNext<CYObjCKeyValue>
+{
+    CYExpression *key_;
+    CYExpression *value_;
+
+    CYObjCKeyValue(CYExpression *key, CYExpression *value, CYObjCKeyValue *next) :
+        CYNext<CYObjCKeyValue>(next),
+        key_(key),
+        value_(value)
+    {
+    }
+};
+
+struct CYObjCDictionary :
+    CYTarget
+{
+    CYObjCKeyValue *pairs_;
+
+    CYObjCDictionary(CYObjCKeyValue *pairs) :
+        pairs_(pairs)
+    {
+    }
+
+    CYPrecedence(0)
+
+    virtual CYTarget *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
 struct CYSelectorPart :
     CYNext<CYSelectorPart>,
     CYThing
 struct CYSelectorPart :
     CYNext<CYSelectorPart>,
     CYThing
index 2a1bf22e61aa7f5d99cabbd9375a1ae2f567f78d..acda20a719a51fdbd1d724d57d2d0647d986c3e8 100644 (file)
@@ -90,6 +90,7 @@
 @end
 
 @begin ObjectiveC
 @end
 
 @begin ObjectiveC
+%union { CYObjCKeyValue *keyValue_; }
 %union { CYImplementationField *implementationField_; }
 %union { CYMessage *message_; }
 %union { CYMessageParameter *messageParameter_; }
 %union { CYImplementationField *implementationField_; }
 %union { CYMessage *message_; }
 %union { CYMessageParameter *messageParameter_; }
@@ -477,11 +478,11 @@ type; })
 %type <argument_> ArgumentListOpt
 %type <argument_> Arguments
 %type <target_> ArrayComprehension
 %type <argument_> ArgumentListOpt
 %type <argument_> Arguments
 %type <target_> ArrayComprehension
+%type <element_> ArrayElement
 %type <literal_> ArrayLiteral
 %type <expression_> ArrowFunction
 %type <functionParameter_> ArrowParameters
 %type <expression_> AssignmentExpression
 %type <literal_> ArrayLiteral
 %type <expression_> ArrowFunction
 %type <functionParameter_> ArrowParameters
 %type <expression_> AssignmentExpression
-%type <expression_> AssignmentExpressionOpt
 %type <identifier_> BindingIdentifier
 %type <identifier_> BindingIdentifierOpt
 %type <bindings_> BindingList_
 %type <identifier_> BindingIdentifier
 %type <identifier_> BindingIdentifierOpt
 %type <bindings_> BindingList_
@@ -520,6 +521,7 @@ type; })
 %type <statement_> Declaration_
 %type <statement_> Declaration
 %type <clause_> DefaultClause
 %type <statement_> Declaration_
 %type <statement_> Declaration
 %type <clause_> DefaultClause
+%type <element_> ElementList_
 %type <element_> ElementList
 %type <element_> ElementListOpt
 %type <statement_> ElseStatementOpt
 %type <element_> ElementList
 %type <element_> ElementListOpt
 %type <statement_> ElseStatementOpt
@@ -693,6 +695,9 @@ type; })
 %type <protocol_> ClassProtocolsOpt
 %type <implementationField_> ImplementationFieldListOpt
 %type <statement_> ImplementationStatement
 %type <protocol_> ClassProtocolsOpt
 %type <implementationField_> ImplementationFieldListOpt
 %type <statement_> ImplementationStatement
+%type <keyValue_> KeyValuePairList_
+%type <keyValue_> KeyValuePairList
+%type <keyValue_> KeyValuePairListOpt
 %type <target_> MessageExpression
 %type <messageParameter_> MessageParameter
 %type <messageParameter_> MessageParameters
 %type <target_> MessageExpression
 %type <messageParameter_> MessageParameter
 %type <messageParameter_> MessageParameters
@@ -1050,10 +1055,19 @@ ArrayLiteral
     : "[" ElementListOpt[elements] "]" { $$ = CYNew CYArray($elements); }
     ;
 
     : "[" ElementListOpt[elements] "]" { $$ = CYNew CYArray($elements); }
     ;
 
-ElementList
-    : AssignmentExpressionOpt[value] "," ElementListOpt[next] { $$ = CYNew CYElementValue($value, $next); }
+ArrayElement
+    : AssignmentExpression[value] { $$ = CYNew CYElementValue($value); }
     | LexOf "..." AssignmentExpression[values] { $$ = CYNew CYElementSpread($values); }
     | LexOf "..." AssignmentExpression[values] { $$ = CYNew CYElementSpread($values); }
-    | AssignmentExpression[value] { $$ = CYNew CYElementValue($value, NULL); }
+    ;
+
+ElementList_
+    : "," ElementListOpt[elements] { $$ = $elements; } 
+    | { $$ = NULL; }
+    ;
+
+ElementList
+    : ArrayElement[element] ElementList_[next] { $$ = $element; $$->SetNext($next); }
+    | LexOf "," ElementListOpt[next] { $$ = CYNew CYElementValue(NULL, $next); }
     ;
 
 ElementListOpt
     ;
 
 ElementListOpt
@@ -1342,11 +1356,6 @@ AssignmentExpression
     | ArrowFunction[pass] { $$ = $pass; }
     | LexOf LeftHandSideAssignment[assignment] AssignmentExpression[rhs] { $assignment->SetRight($rhs); $$ = $assignment; }
     ;
     | ArrowFunction[pass] { $$ = $pass; }
     | LexOf LeftHandSideAssignment[assignment] AssignmentExpression[rhs] { $assignment->SetRight($rhs); $$ = $assignment; }
     ;
-
-AssignmentExpressionOpt
-    : AssignmentExpression[pass] { $$ = $pass; }
-    | LexOf { $$ = NULL; }
-    ;
 /* }}} */
 /* 12.15 Comma Operator ( , ) {{{ */
 Expression
 /* }}} */
 /* 12.15 Comma Operator ( , ) {{{ */
 Expression
@@ -2272,15 +2281,29 @@ BoxableExpression
     | BooleanLiteral[pass] { $$ = $pass; }
     | NumericLiteral[pass] { $$ = $pass; }
     | StringLiteral[pass] { $$ = $pass; }
     | BooleanLiteral[pass] { $$ = $pass; }
     | NumericLiteral[pass] { $$ = $pass; }
     | StringLiteral[pass] { $$ = $pass; }
-    | ArrayLiteral[pass] { $$ = $pass; }
-    | ObjectLiteral[pass] { $$ = $pass; }
     | CoverParenthesizedExpressionAndArrowParameterList[pass] { $$ = $pass; }
     | "YES" { $$ = CYNew CYTrue(); }
     | "NO" { $$ = CYNew CYFalse(); }
     ;
 
     | CoverParenthesizedExpressionAndArrowParameterList[pass] { $$ = $pass; }
     | "YES" { $$ = CYNew CYTrue(); }
     | "NO" { $$ = CYNew CYFalse(); }
     ;
 
+KeyValuePairList_
+    : "," KeyValuePairListOpt[next] { $$ = $next; }
+    | { $$ = NULL; }
+
+KeyValuePairList
+    : AssignmentExpression[key] ":" AssignmentExpression[value] KeyValuePairList_[next] { $$ = CYNew CYObjCKeyValue($key, $value, $next); }
+    ;
+
+KeyValuePairListOpt
+    : KeyValuePairList[pass] { $$ = $pass; }
+    | LexOf { $$ = NULL; }
+    ;
+
 PrimaryExpression
     : "@" BoxableExpression[expression] { $$ = CYNew CYBox($expression); }
 PrimaryExpression
     : "@" BoxableExpression[expression] { $$ = CYNew CYBox($expression); }
+    | "@" "[" ElementListOpt[elements] "]" { $$ = CYNew CYObjCArray($elements); }
+    | "@" "{" KeyValuePairListOpt[pairs] "}" { $$ = CYNew CYObjCDictionary($pairs); }
+
     | "@YES" { $$ = CYNew CYBox(CYNew CYTrue()); }
     | "@NO" { $$ = CYNew CYBox(CYNew CYFalse()); }
     | "@true" { $$ = CYNew CYBox(CYNew CYTrue()); }
     | "@YES" { $$ = CYNew CYBox(CYNew CYTrue()); }
     | "@NO" { $$ = CYNew CYBox(CYNew CYFalse()); }
     | "@true" { $$ = CYNew CYBox(CYNew CYTrue()); }
index 1513c8d29d410308f67ffa38458e0f8b166ccb21..ca05d082395cb5f79a4079f27946e1349cb20bfb 100644 (file)
@@ -101,8 +101,8 @@ CYArgument *CYArgument::Replace(CYContext &context) { $T(NULL)
 }
 
 CYTarget *CYArray::Replace(CYContext &context) {
 }
 
 CYTarget *CYArray::Replace(CYContext &context) {
-    if (elements_ != NULL)
-        elements_->Replace(context);
+    CYForEach (element, elements_)
+        element->Replace(context);
     return this;
 }
 
     return this;
 }
 
@@ -347,8 +347,6 @@ void CYElementSpread::Replace(CYContext &context) {
 
 void CYElementValue::Replace(CYContext &context) {
     context.Replace(value_);
 
 void CYElementValue::Replace(CYContext &context) {
     context.Replace(value_);
-    if (next_ != NULL)
-        next_->Replace(context);
 }
 
 CYForInitializer *CYEmpty::Replace(CYContext &context) {
 }
 
 CYForInitializer *CYEmpty::Replace(CYContext &context) {
index 5599f7e27795d9d246b043e13b0b86e2f16e4584..9786ee7be23ed1ed21bd3f9ba7a1928db4a1e51f 100644 (file)
@@ -1089,21 +1089,26 @@ struct CYClause :
 };
 
 struct CYElement :
 };
 
 struct CYElement :
+    CYNext<CYElement>,
     CYThing
 {
     CYThing
 {
+    CYElement(CYElement *next) :
+        CYNext<CYElement>(next)
+    {
+    }
+
     virtual bool Elision() const = 0;
 
     virtual void Replace(CYContext &context) = 0;
 };
 
 struct CYElementValue :
     virtual bool Elision() const = 0;
 
     virtual void Replace(CYContext &context) = 0;
 };
 
 struct CYElementValue :
-    CYNext<CYElement>,
     CYElement
 {
     CYExpression *value_;
 
     CYElementValue(CYExpression *value, CYElement *next = NULL) :
     CYElement
 {
     CYExpression *value_;
 
     CYElementValue(CYExpression *value, CYElement *next = NULL) :
-        CYNext<CYElement>(next),
+        CYElement(next),
         value_(value)
     {
     }
         value_(value)
     {
     }
@@ -1121,7 +1126,8 @@ struct CYElementSpread :
 {
     CYExpression *value_;
 
 {
     CYExpression *value_;
 
-    CYElementSpread(CYExpression *value) :
+    CYElementSpread(CYExpression *value, CYElement *next = NULL) :
+        CYElement(next),
         value_(value)
     {
     }
         value_(value)
     {
     }