]> git.saurik.com Git - cycript.git/blob - Replace.cpp
Beginnings of FreeBSD portability.
[cycript.git] / Replace.cpp
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
94 CYExpression *CYAddressOf::Replace(CYContext &context) {
95 CYPrefix::Replace(context);
96 return $C0($M(rhs_, $S("$cya")));
97 }
98
99 void CYArgument::Replace(CYContext &context) { $T()
100 context.Replace(value_);
101 next_->Replace(context);
102 }
103
104 CYExpression *CYArray::Replace(CYContext &context) {
105 elements_->Replace(context);
106 return NULL;
107 }
108
109 CYExpression *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
119 CYExpression *CYAssignment::Replace(CYContext &context) {
120 context.Replace(lhs_);
121 context.Replace(rhs_);
122 return NULL;
123 }
124
125 CYStatement *CYBlock::Replace(CYContext &context) {
126 statements_ = statements_->ReplaceAll(context);
127 return NULL;
128 }
129
130 CYStatement *CYBreak::Replace(CYContext &context) {
131 return NULL;
132 }
133
134 CYExpression *CYCall::Replace(CYContext &context) {
135 context.Replace(function_);
136 arguments_->Replace(context);
137 return NULL;
138 }
139
140 void CYCatch::Replace(CYContext &context) { $T()
141 code_.Replace(context);
142 }
143
144 CYStatement *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
154 CYExpression *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
170 CYExpression *CYClassExpression::Replace(CYContext &context) {
171 return Replace_(context);
172 }
173
174 CYStatement *CYClassStatement::Replace(CYContext &context) {
175 return $E(Replace_(context));
176 }
177
178 void CYClause::Replace(CYContext &context) { $T()
179 context.Replace(case_);
180 statements_ = statements_->ReplaceAll(context);
181 next_->Replace(context);
182 }
183
184 CYExpression *CYCompound::Replace(CYContext &context) {
185 expressions_ = expressions_->ReplaceAll(context);
186 return NULL;
187 }
188
189 CYFunctionParameter *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
198 CYStatement *CYComprehension::Replace(CYContext &context, CYStatement *statement) const {
199 return next_ == NULL ? statement : next_->Replace(context, statement);
200 }
201
202 CYExpression *CYCondition::Replace(CYContext &context) {
203 context.Replace(test_);
204 context.Replace(true_);
205 context.Replace(false_);
206 return NULL;
207 }
208
209 CYStatement *CYContinue::Replace(CYContext &context) {
210 return NULL;
211 }
212
213 CYExpression *CYDeclaration::ForEachIn(CYContext &context) {
214 return $ CYVariable(identifier_);
215 }
216
217 void CYDeclaration::Replace(CYContext &context) {
218 context.Replace(initialiser_);
219 }
220
221 void CYDeclarations::Replace(CYContext &context) { $T()
222 declaration_->Replace(context);
223 next_->Replace(context);
224 }
225
226 CYExpression *CYDirectMember::Replace(CYContext &context) {
227 Replace_(context);
228 return NULL;
229 }
230
231 CYStatement *CYDoWhile::Replace(CYContext &context) {
232 context.Replace(test_);
233 context.Replace(code_);
234 return NULL;
235 }
236
237 void CYElement::Replace(CYContext &context) { $T()
238 context.Replace(value_);
239 next_->Replace(context);
240 }
241
242 CYStatement *CYEmpty::Replace(CYContext &context) {
243 return NULL;
244 }
245
246 CYStatement *CYExpress::Replace(CYContext &context) {
247 context.Replace(expression_);
248 return NULL;
249 }
250
251 CYExpression *CYExpression::ClassName(CYContext &context, bool object) {
252 return this;
253 }
254
255 CYExpression *CYExpression::ForEachIn(CYContext &context) {
256 return this;
257 }
258
259 CYExpression *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
271 CYStatement *CYField::Replace(CYContext &context) const {
272 return NULL;
273 }
274
275 void CYFinally::Replace(CYContext &context) { $T()
276 code_.Replace(context);
277 }
278
279 CYStatement *CYFor::Replace(CYContext &context) {
280 // XXX: initialiser_
281 context.Replace(test_);
282 context.Replace(increment_);
283 context.Replace(code_);
284 return NULL;
285 }
286
287 CYStatement *CYForIn::Replace(CYContext &context) {
288 // XXX: initialiser_
289 context.Replace(set_);
290 context.Replace(code_);
291 return NULL;
292 }
293
294 CYFunctionParameter *CYForInComprehension::Parameter(CYContext &context) const {
295 return $ CYFunctionParameter(name_);
296 }
297
298 CYStatement *CYForInComprehension::Replace(CYContext &context, CYStatement *statement) const {
299 return $ CYForIn($ CYVariable(name_), set_, CYComprehension::Replace(context, statement));
300 }
301
302 CYStatement *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
314 CYFunctionParameter *CYForEachInComprehension::Parameter(CYContext &context) const {
315 return $ CYFunctionParameter(name_);
316 }
317
318 CYStatement *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
330 void CYFunction::Replace_(CYContext &context) {
331 code_.Replace(context);
332 }
333
334 CYExpression *CYFunctionExpression::Replace(CYContext &context) {
335 Replace_(context);
336 return NULL;
337 }
338
339 CYStatement *CYFunctionStatement::Replace(CYContext &context) {
340 Replace_(context);
341 return NULL;
342 }
343
344 CYStatement *CYIf::Replace(CYContext &context) {
345 context.Replace(test_);
346 context.Replace(true_);
347 context.Replace(false_);
348 return NULL;
349 }
350
351 CYFunctionParameter *CYIfComprehension::Parameter(CYContext &context) const {
352 return NULL;
353 }
354
355 CYStatement *CYIfComprehension::Replace(CYContext &context, CYStatement *statement) const {
356 return $ CYIf(test_, CYComprehension::Replace(context, statement));
357 }
358
359 CYExpression *CYIndirect::Replace(CYContext &context) {
360 CYPrefix::Replace(context);
361 return $M(rhs_, $S("$cyi"));
362 }
363
364 CYExpression *CYIndirectMember::Replace(CYContext &context) {
365 Replace_(context);
366 return $M($ CYIndirect(object_), property_);
367 }
368
369 CYExpression *CYInfix::Replace(CYContext &context) {
370 context.Replace(lhs_);
371 context.Replace(rhs_);
372 return NULL;
373 }
374
375 CYStatement *CYLabel::Replace(CYContext &context) {
376 context.Replace(statement_);
377 return NULL;
378 }
379
380 void CYMember::Replace_(CYContext &context) {
381 context.Replace(object_);
382 context.Replace(property_);
383 }
384
385 CYStatement *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
404 CYFunctionParameter *CYMessageParameter::Parameters(CYContext &context) const { $T(NULL)
405 CYFunctionParameter *next(next_->Parameters(context));
406 return name_ == NULL ? next : $ CYFunctionParameter(name_, next);
407 }
408
409 CYSelector *CYMessageParameter::Selector(CYContext &context) const {
410 return $ CYSelector(SelectorPart(context));
411 }
412
413 CYSelectorPart *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
418 CYExpression *CYNew::Replace(CYContext &context) {
419 context.Replace(constructor_);
420 arguments_->Replace(context);
421 return NULL;
422 }
423
424 CYExpression *CYObject::Replace(CYContext &context) {
425 properties_->Replace(context);
426 return NULL;
427 }
428
429 CYExpression *CYPostfix::Replace(CYContext &context) {
430 context.Replace(lhs_);
431 return NULL;
432 }
433
434 CYExpression *CYPrefix::Replace(CYContext &context) {
435 context.Replace(rhs_);
436 return NULL;
437 }
438
439 void CYProgram::Replace(CYContext &context) {
440 statements_ = statements_->ReplaceAll(context);
441 }
442
443 void CYProperty::Replace(CYContext &context) { $T()
444 context.Replace(value_);
445 next_->Replace(context);
446 }
447
448 CYStatement *CYReturn::Replace(CYContext &context) {
449 context.Replace(value_);
450 return NULL;
451 }
452
453 CYExpression *CYSelector::Replace(CYContext &context) {
454 return $N1($V("Selector"), name_->Replace(context));
455 }
456
457 CYExpression *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
481 CYString *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
492 CYStatement *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
504 CYStatement *CYSwitch::Replace(CYContext &context) {
505 context.Replace(value_);
506 clauses_->Replace(context);
507 return NULL;
508 }
509
510 CYExpression *CYThis::Replace(CYContext &context) {
511 return NULL;
512 }
513
514 CYStatement *CYThrow::Replace(CYContext &context) {
515 context.Replace(value_);
516 return NULL;
517 }
518
519 CYExpression *CYTrivial::Replace(CYContext &context) {
520 return NULL;
521 }
522
523 CYStatement *CYTry::Replace(CYContext &context) {
524 code_.Replace(context);
525 catch_->Replace(context);
526 finally_->Replace(context);
527 return NULL;
528 }
529
530 CYStatement *CYVar::Replace(CYContext &context) {
531 declarations_->Replace(context);
532 return NULL;
533 }
534
535 CYExpression *CYVariable::Replace(CYContext &context) {
536 return NULL;
537 }
538
539 CYStatement *CYWhile::Replace(CYContext &context) {
540 context.Replace(test_);
541 context.Replace(code_);
542 return NULL;
543 }
544
545 CYStatement *CYWith::Replace(CYContext &context) {
546 context.Replace(scope_);
547 context.Replace(code_);
548 return NULL;
549 }
550
551 CYExpression *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 }