]>
Commit | Line | Data |
---|---|---|
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 | ||
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 | } |