From: Jay Freeman (saurik) Date: Thu, 19 Nov 2009 20:29:18 +0000 (+0000) Subject: Added support for @class protocol lists. X-Git-Tag: v0.9.432~141 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/64b8d29fad73d4dee83b8f0a9f35f30d9cc72846 Added support for @class protocol lists. --- diff --git a/Cycript.y.in b/Cycript.y.in index d439773..ae39422 100644 --- a/Cycript.y.in +++ b/Cycript.y.in @@ -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 ClassMessageDeclarationListOpt %type ClassName %type ClassNameOpt +%type ClassProtocolListOpt +%type ClassProtocols +%type ClassProtocolsOpt %type MessageExpression %type MessageParameter %type 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 diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index 5984ff6..3608867 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -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; } diff --git a/ObjectiveC/Output.mm b/ObjectiveC/Output.mm index 1121121..d8f8345 100644 --- a/ObjectiveC/Output.mm +++ b/ObjectiveC/Output.mm @@ -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_ << ')'; } diff --git a/ObjectiveC/Replace.mm b/ObjectiveC/Replace.mm index 0993a11..fbd9934 100644 --- a/ObjectiveC/Replace.mm +++ b/ObjectiveC/Replace.mm @@ -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)); } diff --git a/ObjectiveC/Syntax.hpp b/ObjectiveC/Syntax.hpp index f4101fb..d8f57ec 100644 --- a/ObjectiveC/Syntax.hpp +++ b/ObjectiveC/Syntax.hpp @@ -122,15 +122,33 @@ struct CYMessage : void Output(CYOutput &out, bool replace) const; }; +struct CYProtocol : + CYNext, + CYThing +{ + CYExpression *name_; + + CYProtocol(CYExpression *name, CYProtocol *next = NULL) : + CYNext(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) { }