]> git.saurik.com Git - cycript.git/commitdiff
Added support for @class protocol lists.
authorJay Freeman (saurik) <saurik@saurik.com>
Thu, 19 Nov 2009 20:29:18 +0000 (20:29 +0000)
committerJay Freeman (saurik) <saurik@saurik.com>
Thu, 19 Nov 2009 20:29:18 +0000 (20:29 +0000)
Cycript.y.in
ObjectiveC/Library.mm
ObjectiveC/Output.mm
ObjectiveC/Replace.mm
ObjectiveC/Syntax.hpp

index d4397730ebc88be855eee167ebe102bf8e319ca2..ae394227c599c8da37493bd64a7efcc3deec6a1c 100644 (file)
@@ -88,6 +88,7 @@ typedef struct {
         CYProgram *program_;
         CYProperty *property_;
         CYPropertyName *propertyName_;
+        CYProtocol *protocol_;
         CYStatement *statement_;
         CYString *string_;
         CYThis *this_;
@@ -481,6 +482,9 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner);
 %type <message_> ClassMessageDeclarationListOpt
 %type <className_> ClassName
 %type <className_> ClassNameOpt
+%type <protocol_> ClassProtocolListOpt
+%type <protocol_> ClassProtocols
+%type <protocol_> ClassProtocolsOpt
 %type <expression_> MessageExpression
 %type <messageParameter_> MessageParameter
 %type <messageParameter_> MessageParameters
@@ -1541,12 +1545,27 @@ ClassNameOpt
     | { $$ = NULL; }
     ;
 
+// XXX: this should be AssignmentExpressionNoRight
+ClassProtocols
+    : ShiftExpression ClassProtocolsOpt { $$ = new(driver.pool_) CYProtocol($1, $2); }
+    ;
+
+ClassProtocolsOpt
+    : "," ClassProtocols { $$ = $2; }
+    | { $$ = NULL; }
+    ;
+
+ClassProtocolListOpt
+    : "<" ClassProtocols ">" { $$ = $2; }
+    | { $$ = NULL; }
+    ;
+
 ClassExpression
-    : "@class" ClassNameOpt ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new(driver.pool_) CYClassExpression($2, $3, $4, $5); }
+    : "@class" ClassNameOpt ClassSuperOpt ClassProtocolListOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new(driver.pool_) CYClassExpression($2, $3, $4, $5, $6); }
     ;
 
 ClassStatement
-    : "@class" ClassName ClassSuperOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new(driver.pool_) CYClassStatement($2, $3, $4, $5); }
+    : "@class" ClassName ClassSuperOpt ClassProtocolListOpt ClassFieldList ClassMessageDeclarationListOpt "@end" { $$ = new(driver.pool_) CYClassStatement($2, $3, $4, $5, $6); }
     ;
 
 CategoryStatement
index 5984ff6ac35466bae854567aff2ee5946f38e36c..3608867211f5f80331117812b91f4d156cc10248 100644 (file)
@@ -1332,6 +1332,8 @@ JSValueRef CYObjectiveC_RuntimeProperty(JSContextRef context, CYUTF8String name)
         return Instance::Make(context, nil);
     if (Class _class = objc_getClass(name.data))
         return CYMakeInstance(context, _class, true);
+    if (Protocol *protocol = objc_getProtocol(name.data))
+        return CYMakeInstance(context, protocol, true);
     return NULL;
 } CYPoolCatch(NULL) return /*XXX*/ NULL; }
 
index 1121121c33963e8806783f509e3b53bf4309f20b..d8f8345d1b822bbb8c064a09ffe9b52e38e812fa 100644 (file)
@@ -70,6 +70,11 @@ void CYClass::Output(CYOutput &out, CYFlags flags) const {
         fields_->Output(out);
     if (messages_ != NULL)
         messages_->Output(out, false);
+    if (protocols_ != NULL) {
+        out << '<';
+        out << *protocols_;
+        out << '>';
+    }
     out << "objc_registerClassPair($cyc);";
     out << "return $cyc;";
     out << "}(";
@@ -104,6 +109,12 @@ void CYMessage::Output(CYOutput &out, bool replace) const {
     out << code_;
 }
 
+void CYProtocol::Output(CYOutput &out) const {
+    name_->Output(out, CYPA, CYNoFlags);
+    if (next_ != NULL)
+        out << ',' << ' ' << *next_;
+}
+
 void CYSelector::Output(CYOutput &out, CYFlags flags) const {
     out << "@selector" << '(' << name_ << ')';
 }
index 0993a118214e4bb5cff5a4e022b92a6d4d3fb6e7..fbd99343065c170b4786c271cf1d481e4d5d5bd4 100644 (file)
@@ -63,6 +63,7 @@ CYExpression *CYClass::Replace_(CYContext &context) {
         $E($ CYAssign($V("$cyp"), $C1($V("object_getClass"), cys)))->*
         $E($ CYAssign(cyc, $C3($V("objc_allocateClassPair"), cys, name, $D(0))))->*
         $E($ CYAssign($V("$cym"), $C1($V("object_getClass"), cyc)))->*
+        protocols_->Replace(context)->*
         fields_->Replace(context)->*
         messages_->Replace(context, false)->*
         $E($C1($V("objc_registerClassPair"), cyc))->*
@@ -118,6 +119,15 @@ CYSelectorPart *CYMessageParameter::SelectorPart(CYContext &context) const { $T(
     return tag_ == NULL ? next : $ CYSelectorPart(tag_, name_ != NULL, next);
 }
 
+CYStatement *CYProtocol::Replace(CYContext &context) const { $T(NULL)
+    return $ CYBlock($$->*
+        next_->Replace(context)->*
+        $E($C2($V("class_addProtocol"),
+            $V("$cyc"), name_
+        ))
+    );
+}
+
 CYExpression *CYSelector::Replace(CYContext &context) {
     return $N1($V("Selector"), name_->Replace(context));
 }
index f4101fb547783a585de01887b82bdf839ab87ff5..d8f57ec88cc6810dc65e89673a009e24f5bda800 100644 (file)
@@ -122,15 +122,33 @@ struct CYMessage :
     void Output(CYOutput &out, bool replace) const;
 };
 
+struct CYProtocol :
+    CYNext<CYProtocol>,
+    CYThing
+{
+    CYExpression *name_;
+
+    CYProtocol(CYExpression *name, CYProtocol *next = NULL) :
+        CYNext<CYProtocol>(next),
+        name_(name)
+    {
+    }
+
+    CYStatement *Replace(CYContext &context) const;
+    void Output(CYOutput &out) const;
+};
+
 struct CYClass {
     CYClassName *name_;
     CYExpression *super_;
+    CYProtocol *protocols_;
     CYField *fields_;
     CYMessage *messages_;
 
-    CYClass(CYClassName *name, CYExpression *super, CYField *fields, CYMessage *messages) :
+    CYClass(CYClassName *name, CYExpression *super, CYProtocol *protocols, CYField *fields, CYMessage *messages) :
         name_(name),
         super_(super),
+        protocols_(protocols),
         fields_(fields),
         messages_(messages)
     {
@@ -147,8 +165,8 @@ struct CYClassExpression :
     CYClass,
     CYExpression
 {
-    CYClassExpression(CYClassName *name, CYExpression *super, CYField *fields, CYMessage *messages) :
-        CYClass(name, super, fields, messages)
+    CYClassExpression(CYClassName *name, CYExpression *super, CYProtocol *protocols, CYField *fields, CYMessage *messages) :
+        CYClass(name, super, protocols, fields, messages)
     {
     }
 
@@ -162,8 +180,8 @@ struct CYClassStatement :
     CYClass,
     CYStatement
 {
-    CYClassStatement(CYClassName *name, CYExpression *super, CYField *fields, CYMessage *messages) :
-        CYClass(name, super, fields, messages)
+    CYClassStatement(CYClassName *name, CYExpression *super, CYProtocol *protocols, CYField *fields, CYMessage *messages) :
+        CYClass(name, super, protocols, fields, messages)
     {
     }