]> git.saurik.com Git - cycript.git/blame - Replace.cpp
Started working on making the build environment more portable.
[cycript.git] / Replace.cpp
CommitLineData
3b52fd1a
JF
1#include "Parser.hpp"
2
3#include <iostream>
4#include <iomanip>
5
6#include <objc/runtime.h>
7#include <sstream>
8
9#define $ \
10 new(context.pool_)
11
12#define $D(args...) \
13 ($ CYNumber(args))
14#define $E(args...) \
15 ($ CYExpress(args))
16#define $F(args...) \
17 ($ CYFunctionExpression(args))
18#define $I(args...) \
19 ($ CYIdentifier(args))
20#define $M(args...) \
21 ($ CYDirectMember(args))
22#define $P(args...) \
23 ($ CYFunctionParameter(args))
24#define $S(args...) \
25 ($ CYString(args))
26#define $V(name) \
27 ($ CYVariable($I(name)))
28
29#define $T(value) \
30 if (this == NULL) \
31 return value;
32#define $$ \
33 CYStatements()
34
35#define $P1(arg0, args...) \
36 $P($I(arg0), ##args)
37#define $P2(arg0, arg1, args...) \
38 $P($I(arg0), $P1(arg1, ##args))
39#define $P3(arg0, arg1, arg2, args...) \
40 $P($I(arg0), $P2(arg1, arg2, ##args))
41#define $P4(arg0, arg1, arg2, arg3, args...) \
42 $P($I(arg0), $P3(arg1, arg2, arg3, ##args))
43#define $P5(arg0, arg1, arg2, arg3, arg4, args...) \
44 $P($I(arg0), $P4(arg1, arg2, arg3, arg4, ##args))
45#define $P6(arg0, arg1, arg2, arg3, arg4, arg5, args...) \
46 $P($I(arg0), $P5(arg1, arg2, arg3, arg4, arg5, ##args))
47
48#define $C(args...) \
49 ($ CYCall(args))
50#define $C_(args...) \
51 ($ CYArgument(args))
52#define $N(args...) \
53 ($ CYNew(args))
54
55#define $C1_(arg0, args...) \
56 $C_(arg0, ##args)
57#define $C2_(arg0, arg1, args...) \
58 $C_(arg0, $C1_(arg1, ##args))
59#define $C3_(arg0, arg1, arg2, args...) \
60 $C_(arg0, $C2_(arg1, arg2, ##args))
61#define $C4_(arg0, arg1, arg2, arg3, args...) \
62 $C_(arg0, $C3_(arg1, arg2, arg3, ##args))
63#define $C5_(arg0, arg1, arg2, arg3, arg4, args...) \
64 $C_(arg0, $C4_(arg1, arg2, arg3, arg4, ##args))
65#define $C6_(arg0, arg1, arg2, arg3, arg4, arg5, args...) \
66 $C_(arg0, $C5_(arg1, arg2, arg3, arg4, arg5, ##args))
67
68#define $C0(func, args...) \
69 $C(func, ##args)
70#define $C1(func, args...) \
71 $C(func, $C1_(args))
72#define $C2(func, args...) \
73 $C(func, $C2_(args))
74#define $C3(func, args...) \
75 $C(func, $C3_(args))
76#define $C4(func, args...) \
77 $C(func, $C4_(args))
78#define $C5(func, args...) \
79 $C(func, $C5_(args))
80
81#define $N0(func, args...) \
82 $N(func, ##args)
83#define $N1(func, args...) \
84 $N(func, $C1_(args))
85#define $N2(func, args...) \
86 $N(func, $C2_(args))
87#define $N3(func, args...) \
88 $N(func, $C3_(args))
89#define $N4(func, args...) \
90 $N(func, $C4_(args))
91#define $N5(func, args...) \
92 $N(func, $C5_(args))
93
94CYExpression *CYAddressOf::Replace(CYContext &context) {
95 CYPrefix::Replace(context);
96 return $C0($M(rhs_, $S("$cya")));
97}
98
99void CYArgument::Replace(CYContext &context) { $T()
100 context.Replace(value_);
101 next_->Replace(context);
102}
103
104CYExpression *CYArray::Replace(CYContext &context) {
105 elements_->Replace(context);
106 return NULL;
107}
108
109CYExpression *CYArrayComprehension::Replace(CYContext &context) {
110 CYVariable *cyv($V("$cyv"));
111
112 return $C0($F(NULL, $P1("$cyv", comprehensions_->Parameters(context)), $$->*
113 $E($ CYAssign(cyv, $ CYArray()))->*
114 comprehensions_->Replace(context, $E($C1($M(cyv, $S("push")), expression_)))->*
115 $ CYReturn(cyv)
116 ));
117}
118
119CYExpression *CYAssignment::Replace(CYContext &context) {
120 context.Replace(lhs_);
121 context.Replace(rhs_);
122 return NULL;
123}
124
125CYStatement *CYBlock::Replace(CYContext &context) {
126 statements_ = statements_->ReplaceAll(context);
127 return NULL;
128}
129
130CYStatement *CYBreak::Replace(CYContext &context) {
131 return NULL;
132}
133
134CYExpression *CYCall::Replace(CYContext &context) {
135 context.Replace(function_);
136 arguments_->Replace(context);
137 return NULL;
138}
139
140void CYCatch::Replace(CYContext &context) { $T()
141 code_.Replace(context);
142}
143
144CYStatement *CYCategory::Replace(CYContext &context) {
145 CYVariable *cyc($V("$cyc")), *cys($V("$cys"));
146
147 return $E($C1($F(NULL, $P5("$cys", "$cyp", "$cyc", "$cyn", "$cyt"), $$->*
148 $E($ CYAssign($V("$cyp"), $C1($V("object_getClass"), cys)))->*
149 $E($ CYAssign(cyc, cys))->*
150 messages_->Replace(context, true)
151 ), name_->ClassName(context, true)));
152}
153
154CYExpression *CYClass::Replace_(CYContext &context) {
155 CYVariable *cyc($V("$cyc")), *cys($V("$cys"));
156
157 CYExpression *name(name_ != NULL ? name_->ClassName(context, false) : $C1($V("$cyq"), $S("CY$")));
158
159 return $C1($F(NULL, $P6("$cys", "$cyp", "$cyc", "$cyn", "$cyt", "$cym"), $$->*
160 $E($ CYAssign($V("$cyp"), $C1($V("object_getClass"), cys)))->*
161 $E($ CYAssign(cyc, $C3($V("objc_allocateClassPair"), cys, name, $D(0))))->*
162 $E($ CYAssign($V("$cym"), $C1($V("object_getClass"), cyc)))->*
163 fields_->Replace(context)->*
164 messages_->Replace(context, false)->*
165 $E($C1($V("objc_registerClassPair"), cyc))->*
166 $ CYReturn(cyc)
167 ), super_ == NULL ? $ CYNull() : super_);
168}
169
170CYExpression *CYClassExpression::Replace(CYContext &context) {
171 return Replace_(context);
172}
173
174CYStatement *CYClassStatement::Replace(CYContext &context) {
175 return $E(Replace_(context));
176}
177
178void CYClause::Replace(CYContext &context) { $T()
179 context.Replace(case_);
180 statements_ = statements_->ReplaceAll(context);
181 next_->Replace(context);
182}
183
184CYExpression *CYCompound::Replace(CYContext &context) {
185 expressions_ = expressions_->ReplaceAll(context);
186 return NULL;
187}
188
189CYFunctionParameter *CYComprehension::Parameters(CYContext &context) const { $T(NULL)
190 CYFunctionParameter *next(next_->Parameters(context));
191 if (CYFunctionParameter *parameter = Parameter(context)) {
192 parameter->SetNext(next);
193 return parameter;
194 } else
195 return next;
196}
197
198CYStatement *CYComprehension::Replace(CYContext &context, CYStatement *statement) const {
199 return next_ == NULL ? statement : next_->Replace(context, statement);
200}
201
202CYExpression *CYCondition::Replace(CYContext &context) {
203 context.Replace(test_);
204 context.Replace(true_);
205 context.Replace(false_);
206 return NULL;
207}
208
209CYStatement *CYContinue::Replace(CYContext &context) {
210 return NULL;
211}
212
213CYExpression *CYDeclaration::ForEachIn(CYContext &context) {
214 return $ CYVariable(identifier_);
215}
216
217void CYDeclaration::Replace(CYContext &context) {
218 context.Replace(initialiser_);
219}
220
221void CYDeclarations::Replace(CYContext &context) { $T()
222 declaration_->Replace(context);
223 next_->Replace(context);
224}
225
226CYExpression *CYDirectMember::Replace(CYContext &context) {
227 Replace_(context);
228 return NULL;
229}
230
231CYStatement *CYDoWhile::Replace(CYContext &context) {
232 context.Replace(test_);
233 context.Replace(code_);
234 return NULL;
235}
236
237void CYElement::Replace(CYContext &context) { $T()
238 context.Replace(value_);
239 next_->Replace(context);
240}
241
242CYStatement *CYEmpty::Replace(CYContext &context) {
243 return NULL;
244}
245
246CYStatement *CYExpress::Replace(CYContext &context) {
247 context.Replace(expression_);
248 return NULL;
249}
250
251CYExpression *CYExpression::ClassName(CYContext &context, bool object) {
252 return this;
253}
254
255CYExpression *CYExpression::ForEachIn(CYContext &context) {
256 return this;
257}
258
259CYExpression *CYExpression::ReplaceAll(CYContext &context) { $T(NULL)
260 CYExpression *replace(this);
261 context.Replace(replace);
262
263 if (CYExpression *next = next_->ReplaceAll(context))
264 replace->SetNext(next);
265 else
266 replace->SetNext(next_);
267
268 return replace;
269}
270
271CYStatement *CYField::Replace(CYContext &context) const {
272 return NULL;
273}
274
275void CYFinally::Replace(CYContext &context) { $T()
276 code_.Replace(context);
277}
278
279CYStatement *CYFor::Replace(CYContext &context) {
280 // XXX: initialiser_
281 context.Replace(test_);
282 context.Replace(increment_);
283 context.Replace(code_);
284 return NULL;
285}
286
287CYStatement *CYForIn::Replace(CYContext &context) {
288 // XXX: initialiser_
289 context.Replace(set_);
290 context.Replace(code_);
291 return NULL;
292}
293
294CYFunctionParameter *CYForInComprehension::Parameter(CYContext &context) const {
295 return $ CYFunctionParameter(name_);
296}
297
298CYStatement *CYForInComprehension::Replace(CYContext &context, CYStatement *statement) const {
299 return $ CYForIn($ CYVariable(name_), set_, CYComprehension::Replace(context, statement));
300}
301
302CYStatement *CYForEachIn::Replace(CYContext &context) {
303 CYVariable *cys($V("$cys")), *cyt($V("$cyt"));
304
305 return $ CYWith($ CYObject($ CYProperty($S("$cys"), $D(0), $ CYProperty($S("$cyt"), $D(0)))), $ CYBlock($$->*
306 $E($ CYAssign(cys, set_))->*
307 $ CYForIn(cyt, cys, $ CYBlock($$->*
308 $E($ CYAssign(initialiser_->ForEachIn(context), $M(cys, cyt)))->*
309 code_
310 ))
311 ));
312}
313
314CYFunctionParameter *CYForEachInComprehension::Parameter(CYContext &context) const {
315 return $ CYFunctionParameter(name_);
316}
317
318CYStatement *CYForEachInComprehension::Replace(CYContext &context, CYStatement *statement) const {
319 CYVariable *cys($V("$cys")), *name($ CYVariable(name_));
320
321 return $E($C0($F(NULL, $P1("$cys"), $$->*
322 $E($ CYAssign(cys, set_))->*
323 $ CYForIn(name, cys, $ CYBlock($$->*
324 $E($ CYAssign(name, $M(cys, name)))->*
325 CYComprehension::Replace(context, statement)
326 ))
327 )));
328}
329
330void CYFunction::Replace_(CYContext &context) {
331 code_.Replace(context);
332}
333
334CYExpression *CYFunctionExpression::Replace(CYContext &context) {
335 Replace_(context);
336 return NULL;
337}
338
339CYStatement *CYFunctionStatement::Replace(CYContext &context) {
340 Replace_(context);
341 return NULL;
342}
343
344CYStatement *CYIf::Replace(CYContext &context) {
345 context.Replace(test_);
346 context.Replace(true_);
347 context.Replace(false_);
348 return NULL;
349}
350
351CYFunctionParameter *CYIfComprehension::Parameter(CYContext &context) const {
352 return NULL;
353}
354
355CYStatement *CYIfComprehension::Replace(CYContext &context, CYStatement *statement) const {
356 return $ CYIf(test_, CYComprehension::Replace(context, statement));
357}
358
359CYExpression *CYIndirect::Replace(CYContext &context) {
360 CYPrefix::Replace(context);
361 return $M(rhs_, $S("$cyi"));
362}
363
364CYExpression *CYIndirectMember::Replace(CYContext &context) {
365 Replace_(context);
366 return $M($ CYIndirect(object_), property_);
367}
368
369CYExpression *CYInfix::Replace(CYContext &context) {
370 context.Replace(lhs_);
371 context.Replace(rhs_);
372 return NULL;
373}
374
375CYStatement *CYLabel::Replace(CYContext &context) {
376 context.Replace(statement_);
377 return NULL;
378}
379
380void CYMember::Replace_(CYContext &context) {
381 context.Replace(object_);
382 context.Replace(property_);
383}
384
385CYStatement *CYMessage::Replace(CYContext &context, bool replace) const { $T(NULL)
386 CYVariable *cyn($V("$cyn"));
387 CYVariable *cyt($V("$cyt"));
388
389 return $ CYBlock($$->*
390 next_->Replace(context, replace)->*
391 $E($ CYAssign(cyn, parameters_->Selector(context)))->*
392 $E($ CYAssign(cyt, $C1($M(cyn, $S("type")), $V(instance_ ? "$cys" : "$cyp"))))->*
393 $E($C4($V(replace ? "class_replaceMethod" : "class_addMethod"),
394 $V(instance_ ? "$cyc" : "$cym"),
395 cyn,
396 $N2($V("Functor"), $F(NULL, $P2("self", "_cmd", parameters_->Parameters(context)), $$->*
397 $ CYReturn($C1($M($F(NULL, NULL, statements_), $S("call")), $V("self")))
398 ), cyt),
399 cyt
400 ))
401 );
402}
403
404CYFunctionParameter *CYMessageParameter::Parameters(CYContext &context) const { $T(NULL)
405 CYFunctionParameter *next(next_->Parameters(context));
406 return name_ == NULL ? next : $ CYFunctionParameter(name_, next);
407}
408
409CYSelector *CYMessageParameter::Selector(CYContext &context) const {
410 return $ CYSelector(SelectorPart(context));
411}
412
413CYSelectorPart *CYMessageParameter::SelectorPart(CYContext &context) const { $T(NULL)
414 CYSelectorPart *next(next_->SelectorPart(context));
415 return tag_ == NULL ? next : $ CYSelectorPart(tag_, name_ != NULL, next);
416}
417
418CYExpression *CYNew::Replace(CYContext &context) {
419 context.Replace(constructor_);
420 arguments_->Replace(context);
421 return NULL;
422}
423
424CYExpression *CYObject::Replace(CYContext &context) {
425 properties_->Replace(context);
426 return NULL;
427}
428
429CYExpression *CYPostfix::Replace(CYContext &context) {
430 context.Replace(lhs_);
431 return NULL;
432}
433
434CYExpression *CYPrefix::Replace(CYContext &context) {
435 context.Replace(rhs_);
436 return NULL;
437}
438
439void CYProgram::Replace(CYContext &context) {
440 statements_ = statements_->ReplaceAll(context);
441}
442
443void CYProperty::Replace(CYContext &context) { $T()
444 context.Replace(value_);
445 next_->Replace(context);
446}
447
448CYStatement *CYReturn::Replace(CYContext &context) {
449 context.Replace(value_);
450 return NULL;
451}
452
453CYExpression *CYSelector::Replace(CYContext &context) {
454 return $N1($V("Selector"), name_->Replace(context));
455}
456
457CYExpression *CYSend::Replace(CYContext &context) {
458 std::ostringstream name;
459 CYArgument **argument(&arguments_);
460
461 while (*argument != NULL) {
462 if ((*argument)->name_ != NULL) {
463 name << *(*argument)->name_;
464 (*argument)->name_ = NULL;
465 if ((*argument)->value_ != NULL)
466 name << ':';
467 }
468
469 if ((*argument)->value_ == NULL)
470 *argument = (*argument)->next_;
471 else
472 argument = &(*argument)->next_;
473 }
474
475 SEL sel(sel_registerName(name.str().c_str()));
476 double address(static_cast<double>(reinterpret_cast<uintptr_t>(sel)));
477
478 return $C2($V("objc_msgSend"), self_, $D(address), arguments_);
479}
480
481CYString *CYSelectorPart::Replace(CYContext &context) {
482 std::ostringstream str;
483 for (const CYSelectorPart *part(this); part != NULL; part = part->next_) {
484 if (part->name_ != NULL)
485 str << part->name_->Value();
486 if (part->value_)
487 str << ':';
488 }
489 return $S(apr_pstrdup(context.pool_, str.str().c_str()));
490}
491
492CYStatement *CYStatement::ReplaceAll(CYContext &context) { $T(NULL)
493 CYStatement *replace(this);
494 context.Replace(replace);
495
496 if (CYStatement *next = next_->ReplaceAll(context))
497 replace->SetNext(next);
498 else
499 replace->SetNext(next_);
500
501 return replace;
502}
503
504CYStatement *CYSwitch::Replace(CYContext &context) {
505 context.Replace(value_);
506 clauses_->Replace(context);
507 return NULL;
508}
509
510CYExpression *CYThis::Replace(CYContext &context) {
511 return NULL;
512}
513
514CYStatement *CYThrow::Replace(CYContext &context) {
515 context.Replace(value_);
516 return NULL;
517}
518
519CYExpression *CYTrivial::Replace(CYContext &context) {
520 return NULL;
521}
522
523CYStatement *CYTry::Replace(CYContext &context) {
524 code_.Replace(context);
525 catch_->Replace(context);
526 finally_->Replace(context);
527 return NULL;
528}
529
530CYStatement *CYVar::Replace(CYContext &context) {
531 declarations_->Replace(context);
532 return NULL;
533}
534
535CYExpression *CYVariable::Replace(CYContext &context) {
536 return NULL;
537}
538
539CYStatement *CYWhile::Replace(CYContext &context) {
540 context.Replace(test_);
541 context.Replace(code_);
542 return NULL;
543}
544
545CYStatement *CYWith::Replace(CYContext &context) {
546 context.Replace(scope_);
547 context.Replace(code_);
548 return NULL;
549}
550
551CYExpression *CYWord::ClassName(CYContext &context, bool object) {
552 CYString *name($S(this));
553 if (object)
554 return $C1($V("objc_getClass"), name);
555 else
556 return name;
557}