From: Jay Freeman (saurik) Date: Fri, 8 Jun 2012 09:13:15 +0000 (-0700) Subject: Allow type signatures to be specified on messages. X-Git-Tag: v0.9.457~3 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/9a7c375c914abe95434bb5e4081e2cb2443cf1cd Allow type signatures to be specified on messages. --- diff --git a/Cycript.yy.in b/Cycript.yy.in index 8efb228..6a4f179 100644 --- a/Cycript.yy.in +++ b/Cycript.yy.in @@ -1320,7 +1320,7 @@ MessageScope TypeOpt : "(" Expression ")" { $$ = $2; } - | "(" LexSetRegExp "void" ")" { $$ = NULL; } + | "(" LexSetRegExp "void" ")" { $$ = CYNew CYString("v"); } | { $$ = NULL; } ; diff --git a/ObjectiveC/Replace.cpp b/ObjectiveC/Replace.cpp index f500bd8..fa8b003 100644 --- a/ObjectiveC/Replace.cpp +++ b/ObjectiveC/Replace.cpp @@ -24,6 +24,24 @@ #include +static CYExpression *MessageType(CYContext &context, CYExpression *type, CYMessageParameter *next, CYExpression *extra = NULL) { + if (type == NULL) + return NULL; + + CYExpression *left($C0($M(type, $S("toString")))); + if (extra != NULL) + left = $ CYAdd(left, extra); + + if (next == NULL) + return left; + + CYExpression *right(next->TypeSignature(context)); + if (right == NULL) + return NULL; + + return $ CYAdd(left, right); +} + CYStatement *CYCategory::Replace(CYContext &context) { CYVariable *cyc($V("$cyc")), *cys($V("$cys")); @@ -74,10 +92,12 @@ CYStatement *CYMessage::Replace(CYContext &context, bool replace) const { $T(NUL CYVariable *self($V("self")); CYVariable *_class($V(instance_ ? "$cys" : "$cyp")); + CYExpression *type(TypeSignature(context) ?: $C1($M(cyn, $S("type")), _class)); + return $ CYBlock($$->* next_->Replace(context, replace)->* $E($ CYAssign(cyn, parameters_->Selector(context)))->* - $E($ CYAssign(cyt, $C1($M(cyn, $S("type")), _class)))->* + $E($ CYAssign(cyt, type))->* $E($C4($V(replace ? "class_replaceMethod" : "class_addMethod"), $V(instance_ ? "$cyc" : "$cym"), cyn, @@ -90,6 +110,10 @@ CYStatement *CYMessage::Replace(CYContext &context, bool replace) const { $T(NUL ); } +CYExpression *CYMessage::TypeSignature(CYContext &context) const { + return MessageType(context, type_, parameters_, $S("@:")); +} + CYFunctionParameter *CYMessageParameter::Parameters(CYContext &context) const { $T(NULL) CYFunctionParameter *next(next_->Parameters(context)); return name_ == NULL ? next : $ CYFunctionParameter($ CYDeclaration(name_), next); @@ -104,6 +128,10 @@ CYSelectorPart *CYMessageParameter::SelectorPart(CYContext &context) const { $T( return tag_ == NULL ? next : $ CYSelectorPart(tag_, name_ != NULL, next); } +CYExpression *CYMessageParameter::TypeSignature(CYContext &context) const { + return MessageType(context, type_, next_); +} + CYExpression *CYBox::Replace(CYContext &context) { return $C1($M($V("Instance"), $S("box")), value_); } diff --git a/ObjectiveC/Syntax.hpp b/ObjectiveC/Syntax.hpp index d6787b4..a9a9798 100644 --- a/ObjectiveC/Syntax.hpp +++ b/ObjectiveC/Syntax.hpp @@ -98,6 +98,7 @@ struct CYMessageParameter : CYFunctionParameter *Parameters(CYContext &context) const; CYSelector *Selector(CYContext &context) const; CYSelectorPart *SelectorPart(CYContext &context) const; + CYExpression *TypeSignature(CYContext &context) const; }; struct CYMessage : @@ -118,6 +119,8 @@ struct CYMessage : CYStatement *Replace(CYContext &context, bool replace) const; void Output(CYOutput &out, bool replace) const; + + CYExpression *TypeSignature(CYContext &context) const; }; struct CYProtocol :