]> git.saurik.com Git - cycript.git/blob - Replace.cpp
5a2ed376d8da5a54a2ec217c51e6a69e8f0e3875
[cycript.git] / Replace.cpp
1 /* Cycript - Remove Execution Server and Disassembler
2 * Copyright (C) 2009 Jay Freeman (saurik)
3 */
4
5 /* Modified BSD License {{{ */
6 /*
7 * Redistribution and use in source and binary
8 * forms, with or without modification, are permitted
9 * provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the
12 * above copyright notice, this list of conditions
13 * and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the
15 * above copyright notice, this list of conditions
16 * and the following disclaimer in the documentation
17 * and/or other materials provided with the
18 * distribution.
19 * 3. The name of the author may not be used to endorse
20 * or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
25 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38 /* }}} */
39
40 #include "Parser.hpp"
41
42 #include <iomanip>
43
44 #include "Replace.hpp"
45
46 CYExpression *CYAdd::Replace(CYContext &context) {
47 CYInfix::Replace(context);
48
49 CYExpression *lhp(lhs_->Primitive(context));
50 CYExpression *rhp(rhs_->Primitive(context));
51
52 CYString *lhs(dynamic_cast<CYString *>(lhp));
53 CYString *rhs(dynamic_cast<CYString *>(rhp));
54
55 if (lhs != NULL || rhs != NULL) {
56 if (lhs == NULL) {
57 lhs = lhp->String(context);
58 if (lhs == NULL)
59 return NULL;
60 } else if (rhs == NULL) {
61 rhs = rhp->String(context);
62 if (rhs == NULL)
63 return NULL;
64 }
65
66 return lhs->Concat(context, rhs);
67 }
68
69 if (CYNumber *lhn = lhp->Number(context))
70 if (CYNumber *rhn = rhp->Number(context))
71 return $D(lhn->Value() + rhn->Value());
72
73 return NULL;
74 }
75
76 CYExpression *CYAddressOf::Replace(CYContext &context) {
77 CYPrefix::Replace(context);
78 return $C0($M(rhs_, $S("$cya")));
79 }
80
81 void CYArgument::Replace(CYContext &context) { $T()
82 context.Replace(value_);
83 next_->Replace(context);
84 }
85
86 CYExpression *CYArray::Replace(CYContext &context) {
87 elements_->Replace(context);
88 return NULL;
89 }
90
91 CYExpression *CYArrayComprehension::Replace(CYContext &context) {
92 CYVariable *cyv($V("$cyv"));
93
94 return $C0($F(NULL, $P1("$cyv", comprehensions_->Parameters(context)), $$->*
95 $E($ CYAssign(cyv, $ CYArray()))->*
96 comprehensions_->Replace(context, $E($C1($M(cyv, $S("push")), expression_)))->*
97 $ CYReturn(cyv)
98 ));
99 }
100
101 CYExpression *CYAssignment::Replace(CYContext &context) {
102 context.Replace(lhs_);
103 context.Replace(rhs_);
104 return NULL;
105 }
106
107 CYStatement *CYBlock::Replace(CYContext &context) {
108 statements_ = statements_->ReplaceAll(context);
109 return NULL;
110 }
111
112 CYStatement *CYBreak::Replace(CYContext &context) {
113 return NULL;
114 }
115
116 CYExpression *CYCall::Replace(CYContext &context) {
117 context.Replace(function_);
118 arguments_->Replace(context);
119 return NULL;
120 }
121
122 namespace cy {
123 namespace Syntax {
124
125 void Catch::Replace(CYContext &context) { $T()
126 code_.Replace(context);
127 }
128
129 } }
130
131 void CYClause::Replace(CYContext &context) { $T()
132 context.Replace(case_);
133 statements_ = statements_->ReplaceAll(context);
134 next_->Replace(context);
135 }
136
137 CYExpression *CYCompound::Replace(CYContext &context) {
138 expressions_ = expressions_->ReplaceAll(context);
139 return NULL;
140 }
141
142 CYFunctionParameter *CYComprehension::Parameters(CYContext &context) const { $T(NULL)
143 CYFunctionParameter *next(next_->Parameters(context));
144 if (CYFunctionParameter *parameter = Parameter(context)) {
145 parameter->SetNext(next);
146 return parameter;
147 } else
148 return next;
149 }
150
151 CYStatement *CYComprehension::Replace(CYContext &context, CYStatement *statement) const {
152 return next_ == NULL ? statement : next_->Replace(context, statement);
153 }
154
155 CYExpression *CYCondition::Replace(CYContext &context) {
156 context.Replace(test_);
157 context.Replace(true_);
158 context.Replace(false_);
159 return NULL;
160 }
161
162 CYStatement *CYContinue::Replace(CYContext &context) {
163 return NULL;
164 }
165
166 CYExpression *CYDeclaration::ForEachIn(CYContext &context) {
167 return $ CYVariable(identifier_);
168 }
169
170 void CYDeclaration::Replace(CYContext &context) {
171 context.Replace(initialiser_);
172 }
173
174 void CYDeclarations::Replace(CYContext &context) { $T()
175 declaration_->Replace(context);
176 next_->Replace(context);
177 }
178
179 CYExpression *CYDirectMember::Replace(CYContext &context) {
180 Replace_(context);
181 return NULL;
182 }
183
184 CYStatement *CYDoWhile::Replace(CYContext &context) {
185 context.Replace(test_);
186 context.Replace(code_);
187 return NULL;
188 }
189
190 void CYElement::Replace(CYContext &context) { $T()
191 context.Replace(value_);
192 next_->Replace(context);
193 }
194
195 CYStatement *CYEmpty::Replace(CYContext &context) {
196 return NULL;
197 }
198
199 CYStatement *CYExpress::Replace(CYContext &context) {
200 context.Replace(expression_);
201 return NULL;
202 }
203
204 CYExpression *CYExpression::ClassName(CYContext &context, bool object) {
205 return this;
206 }
207
208 CYExpression *CYExpression::ForEachIn(CYContext &context) {
209 return this;
210 }
211
212 CYExpression *CYExpression::ReplaceAll(CYContext &context) { $T(NULL)
213 CYExpression *replace(this);
214 context.Replace(replace);
215
216 if (CYExpression *next = next_->ReplaceAll(context))
217 replace->SetNext(next);
218 else
219 replace->SetNext(next_);
220
221 return replace;
222 }
223
224 CYNumber *CYFalse::Number(CYContext &context) {
225 return $D(0);
226 }
227
228 CYString *CYFalse::String(CYContext &context) {
229 return $S("false");
230 }
231
232 void CYFinally::Replace(CYContext &context) { $T()
233 code_.Replace(context);
234 }
235
236 CYStatement *CYFor::Replace(CYContext &context) {
237 // XXX: initialiser_
238 context.Replace(test_);
239 context.Replace(increment_);
240 context.Replace(code_);
241 return NULL;
242 }
243
244 CYStatement *CYForIn::Replace(CYContext &context) {
245 // XXX: initialiser_
246 context.Replace(set_);
247 context.Replace(code_);
248 return NULL;
249 }
250
251 CYFunctionParameter *CYForInComprehension::Parameter(CYContext &context) const {
252 return $ CYFunctionParameter(name_);
253 }
254
255 CYStatement *CYForInComprehension::Replace(CYContext &context, CYStatement *statement) const {
256 return $ CYForIn($ CYVariable(name_), set_, CYComprehension::Replace(context, statement));
257 }
258
259 CYStatement *CYForEachIn::Replace(CYContext &context) {
260 CYVariable *cys($V("$cys")), *cyt($V("$cyt"));
261
262 return $ CYWith($ CYObject($ CYProperty($S("$cys"), $D(0), $ CYProperty($S("$cyt"), $D(0)))), $ CYBlock($$->*
263 $E($ CYAssign(cys, set_))->*
264 $ CYForIn(cyt, cys, $ CYBlock($$->*
265 $E($ CYAssign(initialiser_->ForEachIn(context), $M(cys, cyt)))->*
266 code_
267 ))
268 ));
269 }
270
271 CYFunctionParameter *CYForEachInComprehension::Parameter(CYContext &context) const {
272 return $ CYFunctionParameter(name_);
273 }
274
275 CYStatement *CYForEachInComprehension::Replace(CYContext &context, CYStatement *statement) const {
276 CYVariable *cys($V("$cys")), *name($ CYVariable(name_));
277
278 return $E($C0($F(NULL, $P1("$cys"), $$->*
279 $E($ CYAssign(cys, set_))->*
280 $ CYForIn(name, cys, $ CYBlock($$->*
281 $E($ CYAssign(name, $M(cys, name)))->*
282 CYComprehension::Replace(context, statement)
283 ))
284 )));
285 }
286
287 void CYFunction::Replace_(CYContext &context) {
288 code_.Replace(context);
289 }
290
291 CYExpression *CYFunctionExpression::Replace(CYContext &context) {
292 Replace_(context);
293 return NULL;
294 }
295
296 CYStatement *CYFunctionStatement::Replace(CYContext &context) {
297 Replace_(context);
298 return NULL;
299 }
300
301 CYStatement *CYIf::Replace(CYContext &context) {
302 context.Replace(test_);
303 context.Replace(true_);
304 context.Replace(false_);
305 return NULL;
306 }
307
308 CYFunctionParameter *CYIfComprehension::Parameter(CYContext &context) const {
309 return NULL;
310 }
311
312 CYStatement *CYIfComprehension::Replace(CYContext &context, CYStatement *statement) const {
313 return $ CYIf(test_, CYComprehension::Replace(context, statement));
314 }
315
316 CYExpression *CYIndirect::Replace(CYContext &context) {
317 CYPrefix::Replace(context);
318 return $M(rhs_, $S("$cyi"));
319 }
320
321 CYExpression *CYIndirectMember::Replace(CYContext &context) {
322 Replace_(context);
323 return $M($ CYIndirect(object_), property_);
324 }
325
326 CYExpression *CYInfix::Replace(CYContext &context) {
327 context.Replace(lhs_);
328 context.Replace(rhs_);
329 return NULL;
330 }
331
332 CYStatement *CYLabel::Replace(CYContext &context) {
333 context.Replace(statement_);
334 return NULL;
335 }
336
337 void CYMember::Replace_(CYContext &context) {
338 context.Replace(object_);
339 context.Replace(property_);
340 }
341
342 CYExpression *CYNew::Replace(CYContext &context) {
343 context.Replace(constructor_);
344 arguments_->Replace(context);
345 return NULL;
346 }
347
348 CYNumber *CYNull::Number(CYContext &context) {
349 return $D(0);
350 }
351
352 CYString *CYNull::String(CYContext &context) {
353 return $S("null");
354 }
355
356 CYNumber *CYNumber::Number(CYContext &context) {
357 return this;
358 }
359
360 CYString *CYNumber::String(CYContext &context) {
361 // XXX: there is a precise algorithm for this
362 return $S(apr_psprintf(context.pool_, "%.17g", Value()));
363 }
364
365 CYExpression *CYObject::Replace(CYContext &context) {
366 properties_->Replace(context);
367 return NULL;
368 }
369
370 CYExpression *CYPostfix::Replace(CYContext &context) {
371 context.Replace(lhs_);
372 return NULL;
373 }
374
375 CYExpression *CYPrefix::Replace(CYContext &context) {
376 context.Replace(rhs_);
377 return NULL;
378 }
379
380 void CYProgram::Replace(CYContext &context) {
381 statements_ = statements_->ReplaceAll(context);
382 }
383
384 void CYProperty::Replace(CYContext &context) { $T()
385 context.Replace(value_);
386 next_->Replace(context);
387 }
388
389 CYStatement *CYReturn::Replace(CYContext &context) {
390 context.Replace(value_);
391 return NULL;
392 }
393
394 CYStatement *CYStatement::ReplaceAll(CYContext &context) { $T(NULL)
395 CYStatement *replace(this);
396 context.Replace(replace);
397
398 if (CYStatement *next = next_->ReplaceAll(context))
399 replace->SetNext(next);
400 else
401 replace->SetNext(next_);
402
403 return replace;
404 }
405
406 CYString *CYString::Concat(CYContext &context, CYString *rhs) const {
407 size_t size(size_ + rhs->size_);
408 char *value(new(context.pool_) char[size + 1]);
409 memcpy(value, value_, size_);
410 memcpy(value + size_, rhs->value_, rhs->size_);
411 value[size] = '\0';
412 return $S(value);
413 }
414
415 CYNumber *CYString::Number(CYContext &context) {
416 // XXX: there is a precise algorithm for this
417 return NULL;
418 }
419
420 CYString *CYString::String(CYContext &context) {
421 return this;
422 }
423
424 CYStatement *CYSwitch::Replace(CYContext &context) {
425 context.Replace(value_);
426 clauses_->Replace(context);
427 return NULL;
428 }
429
430 CYExpression *CYThis::Replace(CYContext &context) {
431 return NULL;
432 }
433
434 namespace cy {
435 namespace Syntax {
436
437 CYStatement *Throw::Replace(CYContext &context) {
438 context.Replace(value_);
439 return NULL;
440 }
441
442 } }
443
444 CYExpression *CYTrivial::Replace(CYContext &context) {
445 return NULL;
446 }
447
448 CYNumber *CYTrue::Number(CYContext &context) {
449 return $D(1);
450 }
451
452 CYString *CYTrue::String(CYContext &context) {
453 return $S("true");
454 }
455
456 namespace cy {
457 namespace Syntax {
458
459 CYStatement *Try::Replace(CYContext &context) {
460 code_.Replace(context);
461 catch_->Replace(context);
462 finally_->Replace(context);
463 return NULL;
464 }
465
466 } }
467
468 CYStatement *CYVar::Replace(CYContext &context) {
469 declarations_->Replace(context);
470 return NULL;
471 }
472
473 CYExpression *CYVariable::Replace(CYContext &context) {
474 return NULL;
475 }
476
477 CYStatement *CYWhile::Replace(CYContext &context) {
478 context.Replace(test_);
479 context.Replace(code_);
480 return NULL;
481 }
482
483 CYStatement *CYWith::Replace(CYContext &context) {
484 context.Replace(scope_);
485 context.Replace(code_);
486 return NULL;
487 }
488
489 CYExpression *CYWord::ClassName(CYContext &context, bool object) {
490 CYString *name($S(this));
491 if (object)
492 return $C1($V("objc_getClass"), name);
493 else
494 return name;
495 }