]>
git.saurik.com Git - cycript.git/blob - ObjectiveC/Replace.cpp
1 /* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2015 Jay Freeman (saurik)
5 /* GNU Affero General Public License, Version 3 {{{ */
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "Replace.hpp"
26 #include "ObjectiveC/Syntax.hpp"
28 static CYExpression
*MessageType(CYContext
&context
, CYTypedIdentifier
*type
, CYMessageParameter
*next
, CYExpression
*extra
= NULL
) {
29 CYExpression
*left($
C0($
M(type
->Replace(context
), $
S("toString"))));
31 left
= $
CYAdd(left
, extra
);
33 if (next
== NULL
|| next
->type_
== NULL
)
36 CYExpression
*right(next
->TypeSignature(context
));
40 return $
CYAdd(left
, right
);
43 CYStatement
*CYCategory::Replace(CYContext
&context
) {
44 CYVariable
*cyc($
V("$cyc")), *cys($
V("$cys"));
46 return $
E($
C1($
F(NULL
, $
P6($
B($
I("$cys")), $
B($
I("$cyp")), $
B($
I("$cyc")), $
B($
I("$cyn")), $
B($
I("$cyt")), $
B($
I("$cym"))), $$
->*
47 $
E($
CYAssign($
V("$cyp"), $
C1($
V("object_getClass"), cys
)))->*
48 $
E($
CYAssign(cyc
, cys
))->*
49 $
E($
CYAssign($
V("$cym"), $
C1($
V("object_getClass"), cyc
)))->*
50 messages_
->Replace(context
, true)
51 ), $
C1($
V("objc_getClass"), $
S(name_
))));
54 CYStatement
*CYImplementation::Replace(CYContext
&context
) {
55 CYVariable
*cyc($
V("$cyc")), *cys($
V("$cys"));
57 return $
E($
C1($
F(NULL
, $
P6($
B($
I("$cys")), $
B($
I("$cyp")), $
B($
I("$cyc")), $
B($
I("$cyn")), $
B($
I("$cyt")), $
B($
I("$cym"))), $$
->*
58 $
E($
CYAssign($
V("$cyp"), $
C1($
V("object_getClass"), cys
)))->*
59 $
E($
CYAssign(cyc
, $
C3($
V("objc_allocateClassPair"), cys
, $
S(name_
), $
D(0))))->*
60 $
E($
CYAssign($
V("$cym"), $
C1($
V("object_getClass"), cyc
)))->*
61 protocols_
->Replace(context
)->*
62 fields_
->Replace(context
)->*
63 messages_
->Replace(context
, false)->*
64 $
E($
C1($
V("objc_registerClassPair"), cyc
))->*
66 ), extends_
== NULL
? $
CYNull() : extends_
));
69 CYStatement
*CYImplementationField::Replace(CYContext
&context
) const { $
T(NULL
)
70 CYVariable
*cyn($
V("$cyn"));
71 CYVariable
*cyt($
V("$cyt"));
73 CYExpression
*type($
C0($
M(typed_
->Replace(context
), $
S("toString"))));
75 return $
CYBlock($$
->*
76 $
E($
CYAssign(cyt
, type
))->*
77 $
E($
CYAssign(cyn
, $
N1($
V("Type"), cyt
)))->*
78 $
E($
C5($
V("class_addIvar"), $
V("$cyc"), $
S(typed_
->identifier_
->Word()), $
M(cyn
, $
S("size")), $
M(cyn
, $
S("alignment")), cyt
))->*
79 next_
->Replace(context
)
83 CYTarget
*CYInstanceLiteral::Replace(CYContext
&context
) {
84 return $
N1($
V("Instance"), number_
);
87 CYStatement
*CYMessage::Replace(CYContext
&context
, bool replace
) const { $
T(NULL
)
88 CYVariable
*cyn($
V("$cyn"));
89 CYVariable
*cyt($
V("$cyt"));
90 CYVariable
*self($
V("self"));
91 CYVariable
*_class($
V(instance_
? "$cys" : "$cyp"));
93 return $
CYBlock($$
->*
94 next_
->Replace(context
, replace
)->*
95 $
E($
CYAssign(cyn
, parameters_
->Selector(context
)))->*
96 $
E($
CYAssign(cyt
, TypeSignature(context
)))->*
97 $
E($
C4($
V(replace
? "class_replaceMethod" : "class_addMethod"),
98 $
V(instance_
? "$cyc" : "$cym"),
100 $
N2($
V("Functor"), $
F(NULL
, $
P2($
B($
I("self")), $
B($
I("_cmd")), parameters_
->Parameters(context
)), $$
->*
101 $
CYVar($
B1($
B($
I("$cyr"), $
N2($
V("objc_super"), self
, _class
))))->*
102 $
CYReturn($
C1($
M($
F(NULL
, NULL
, code_
.code_
), $
S("call")), self
))
109 CYExpression
*CYMessage::TypeSignature(CYContext
&context
) const {
110 return MessageType(context
, type_
, parameters_
, $
S("@:"));
113 CYFunctionParameter
*CYMessageParameter::Parameters(CYContext
&context
) const { $
T(NULL
)
114 CYFunctionParameter
*next(next_
->Parameters(context
));
115 return type_
== NULL
? next
: $
CYFunctionParameter($
B(type_
->identifier_
), next
);
118 CYSelector
*CYMessageParameter::Selector(CYContext
&context
) const {
119 return $
CYSelector(SelectorPart(context
));
122 CYSelectorPart
*CYMessageParameter::SelectorPart(CYContext
&context
) const { $
T(NULL
)
123 CYSelectorPart
*next(next_
->SelectorPart(context
));
124 return name_
== NULL
? next
: $
CYSelectorPart(name_
, type_
!= NULL
, next
);
127 CYExpression
*CYMessageParameter::TypeSignature(CYContext
&context
) const {
128 return MessageType(context
, type_
, next_
);
131 CYTarget
*CYBox::Replace(CYContext
&context
) {
132 return $
C1($
M($
V("Instance"), $
S("box")), value_
);
135 CYTarget
*CYObjCArray::Replace(CYContext
&context
) {
137 CYForEach (element
, elements_
)
139 return $
CYSendDirect($
V("NSArray"), $
C_($
CYWord("arrayWithObjects"), $
CYArray(elements_
), $
C_($
CYWord("count"), $
D(count
))));
142 CYTarget
*CYObjCDictionary::Replace(CYContext
&context
) {
143 CYList
<CYElement
> keys
;
144 CYList
<CYElement
> values
;
147 CYForEach (pair
, pairs_
) {
148 keys
->*$
CYElementValue(pair
->key_
);
149 values
->*$
CYElementValue(pair
->value_
);
153 return $
CYSendDirect($
V("NSDictionary"), $
C_($
CYWord("dictionaryWithObjects"), $
CYArray(values
), $
C_($
CYWord("forKeys"), $
CYArray(keys
), $
C_($
CYWord("count"), $
D(count
)))));
156 CYTarget
*CYObjCBlock::Replace(CYContext
&context
) {
157 return $
C1($
CYTypeExpression(($
CYTypedIdentifier(*typed_
))->Modify($
CYTypeBlockWith(parameters_
))), $
CYFunctionExpression(NULL
, parameters_
->Parameters(context
), code_
));
160 CYStatement
*CYProtocol::Replace(CYContext
&context
) const { $
T(NULL
)
161 return $
CYBlock($$
->*
162 next_
->Replace(context
)->*
163 $
E($
C2($
V("class_addProtocol"),
169 CYTarget
*CYSelector::Replace(CYContext
&context
) {
170 return $
C1($
V("sel_registerName"), parts_
->Replace(context
));
173 CYString
*CYSelectorPart::Replace(CYContext
&context
) {
174 std::ostringstream str
;
175 CYForEach (part
, this) {
176 if (part
->name_
!= NULL
)
177 str
<< part
->name_
->Word();
181 return $
S($pool
.strdup(str
.str().c_str()));
184 CYTarget
*CYSendDirect::Replace(CYContext
&context
) {
185 std::ostringstream name
;
186 CYArgument
**argument(&arguments_
);
187 CYSelectorPart
*selector(NULL
), *current(NULL
);
189 while (*argument
!= NULL
) {
190 if ((*argument
)->name_
!= NULL
) {
191 CYSelectorPart
*part($
CYSelectorPart((*argument
)->name_
, (*argument
)->value_
!= NULL
));
192 if (selector
== NULL
)
195 current
->SetNext(part
);
197 (*argument
)->name_
= NULL
;
200 if ((*argument
)->value_
== NULL
)
201 *argument
= (*argument
)->next_
;
203 argument
= &(*argument
)->next_
;
206 return $
C2($
V("objc_msgSend"), self_
, selector
->Replace(context
), arguments_
);
209 CYTarget
*CYSendSuper::Replace(CYContext
&context
) {
210 return $
CYSendDirect($
V("$cyr"), arguments_
);