]> git.saurik.com Git - cycript.git/blob - Output.cpp
b8780687a8edf6eddc88bd1b86431bc38267a494
[cycript.git] / Output.cpp
1 #include "Parser.hpp"
2
3 #include <iostream>
4 #include <iomanip>
5
6 #include <objc/runtime.h>
7 #include <sstream>
8
9 _finline CYFlags operator ~(CYFlags rhs) {
10 return static_cast<CYFlags>(~static_cast<unsigned>(rhs));
11 }
12
13 _finline CYFlags operator &(CYFlags lhs, CYFlags rhs) {
14 return static_cast<CYFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs));
15 }
16
17 _finline CYFlags operator |(CYFlags lhs, CYFlags rhs) {
18 return static_cast<CYFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs));
19 }
20
21 _finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) {
22 return lhs = lhs | rhs;
23 }
24
25 _finline CYFlags CYLeft(CYFlags flags) {
26 return flags & ~CYNoTrailer;
27 }
28
29 _finline CYFlags CYCenter(CYFlags flags) {
30 return flags & CYNoIn;
31 }
32
33 _finline CYFlags CYRight(CYFlags flags) {
34 return flags & (CYNoIn | CYNoTrailer | CYNoTerminator);
35 }
36
37 #define CYPA 16
38
39 void OutputBody(CYOutput &out, CYStatement *body) {
40 if (out.pretty_)
41 out << ' ';
42 out << '{';
43 if (out.pretty_)
44 out << '\n';
45 ++out.indent_;
46 if (body != NULL)
47 body->Multiple(out);
48 --out.indent_;
49 out.Indent();
50 out << '}';
51 }
52
53 void CYOutput::Indent() {
54 if (pretty_)
55 for (unsigned i(0); i != indent_; ++i)
56 out_ << " ";
57 }
58
59 void CYAddressOf::Output(CYOutput &out, CYFlags flags) const {
60 rhs_->Output(out, 1, CYLeft(flags));
61 out << ".$cya()";
62 }
63
64 void CYArgument::Output(CYOutput &out) const {
65 if (name_ != NULL) {
66 out << *name_;
67 if (value_ != NULL) {
68 out << ':';
69 if (out.pretty_)
70 out << ' ';
71 }
72 }
73 if (value_ != NULL)
74 value_->Output(out, CYPA, CYNoFlags);
75 if (next_ != NULL) {
76 if (next_->name_ != NULL)
77 out << ' ';
78 else {
79 out << ',';
80 if (out.pretty_)
81 out << ' ';
82 }
83 next_->Output(out);
84 }
85 }
86
87 void CYArray::Output(CYOutput &out, CYFlags flags) const {
88 out << '[';
89 if (elements_ != NULL)
90 elements_->Output(out);
91 out << ']';
92 }
93
94 void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
95 // XXX: I don't necc. need the ()s
96 out << "(function($cyv";
97 for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
98 if (const char *name = comprehension->Name())
99 out << ',' << name;
100 out << "){";
101 out << "$cyv=[];";
102 comprehensions_->Output(out);
103 out << "$cyv.push(";
104 expression_->Output(out, CYPA, CYNoFlags);
105 out << ");";
106 for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
107 comprehension->End_(out);
108 out << "return $cyv;";
109 out << "}())";
110 }
111
112 void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
113 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
114 if (out.pretty_)
115 out << ' ';
116 out << Operator();
117 if (out.pretty_)
118 out << ' ';
119 rhs_->Output(out, Precedence(), CYRight(flags));
120 }
121
122 void CYBlock::Output(CYOutput &out, CYFlags flags) const {
123 statements_->Single(out, flags);
124 }
125
126 void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
127 if ((flags & CYNoLeader) != 0)
128 out << ' ';
129 out << (Value() ? "true" : "false");
130 if ((flags & CYNoTrailer) != 0)
131 out << ' ';
132 }
133
134 void CYBreak::Output(CYOutput &out, CYFlags flags) const {
135 if ((flags & CYNoLeader) != 0)
136 out << ' ';
137 out << "break";
138 if (label_ != NULL)
139 out << ' ' << *label_;
140 if ((flags & CYNoTerminator) == 0)
141 out << ';';
142 else if ((flags & CYNoTrailer) != 0)
143 out << ' ';
144 }
145
146 void CYCall::Output(CYOutput &out, CYFlags flags) const {
147 bool protect((flags & CYNoCall) != 0);
148 if (protect)
149 out << '(';
150 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
151 out << '(';
152 if (arguments_ != NULL)
153 arguments_->Output(out);
154 out << ')';
155 if (protect)
156 out << ')';
157 }
158
159 void CYCatch::Output(CYOutput &out) const {
160 out << "catch";
161 if (out.pretty_)
162 out << ' ';
163 out << '(' << *name_ << ')';
164 if (out.pretty_)
165 out << ' ';
166 out << '{';
167 if (code_ != NULL)
168 code_->Multiple(out);
169 out << '}';
170 }
171
172 void CYCategory::Output(CYOutput &out, CYFlags flags) const {
173 out << "(function($cys,$cyp,$cyc,$cyn,$cyt){";
174 out << "$cyp=object_getClass($cys);";
175 out << "$cyc=$cys;";
176 if (messages_ != NULL)
177 messages_->Output(out, true);
178 out << "})(";
179 name_->ClassName(out, true);
180 out << ')';
181 if ((flags & CYNoTerminator) == 0)
182 out << ';';
183 }
184
185 void CYClass::Output(CYOutput &out, CYFlags flags) const {
186 // XXX: I don't necc. need the ()s
187 out << "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
188 out << "$cyp=object_getClass($cys);";
189 out << "$cyc=objc_allocateClassPair($cys,";
190 if (name_ != NULL)
191 name_->ClassName(out, false);
192 else
193 out << "$cyq(\"CY$\")";
194 out << ",0);";
195 out << "$cym=object_getClass($cyc);";
196 if (fields_ != NULL)
197 fields_->Output(out);
198 if (messages_ != NULL)
199 messages_->Output(out, false);
200 out << "objc_registerClassPair($cyc);";
201 out << "return $cyc;";
202 out << "}(";
203 if (super_ != NULL)
204 super_->Output(out, CYPA, CYNoFlags);
205 else
206 out << "null";
207 out << "))";
208 }
209
210 void CYClassExpression::Output(CYOutput &out, CYFlags flags) const {
211 CYClass::Output(out, flags);
212 }
213
214 void CYClassStatement::Output(CYOutput &out, CYFlags flags) const {
215 CYClass::Output(out, flags);
216 }
217
218 void CYCompound::Output(CYOutput &out, CYFlags flags) const {
219 if (CYExpression *expression = expressions_)
220 if (CYExpression *next = expression->next_) {
221 expression->Output(out, CYLeft(flags));
222 CYFlags center(CYCenter(flags));
223 while (next != NULL) {
224 expression = next;
225 out << ',';
226 if (out.pretty_)
227 out << ' ';
228 next = expression->next_;
229 CYFlags right(next != NULL ? center : CYRight(flags));
230 expression->Output(out, right);
231 }
232 } else
233 expression->Output(out, flags);
234 }
235
236 void CYComprehension::Output(CYOutput &out) const {
237 Begin_(out);
238 if (next_ != NULL)
239 next_->Output(out);
240 }
241
242 void CYCondition::Output(CYOutput &out, CYFlags flags) const {
243 test_->Output(out, Precedence() - 1, CYLeft(flags));
244 if (out.pretty_)
245 out << ' ';
246 out << '?';
247 if (out.pretty_)
248 out << ' ';
249 if (true_ != NULL)
250 true_->Output(out, CYPA, CYNoFlags);
251 if (out.pretty_)
252 out << ' ';
253 out << ':';
254 if (out.pretty_)
255 out << ' ';
256 false_->Output(out, CYPA, CYRight(flags));
257 }
258
259 void CYContinue::Output(CYOutput &out, CYFlags flags) const {
260 if ((flags & CYNoLeader) != 0)
261 out << ' ';
262 out << "continue";
263 if (label_ != NULL)
264 out << ' ' << *label_;
265 if ((flags & CYNoTerminator) == 0)
266 out << ';';
267 else if ((flags & CYNoTrailer) != 0)
268 out << ' ';
269 }
270
271 void CYClause::Output(CYOutput &out) const {
272 if (case_ != NULL) {
273 out << "case";
274 case_->Output(out, CYNoLeader);
275 } else
276 out << "default";
277 out << ':';
278 if (out.pretty_)
279 out << '\n';
280 if (code_ != NULL)
281 code_->Multiple(out, next_ == NULL ? CYNoFlags : CYNoTrailer);
282 if (next_ != NULL)
283 out << *next_;
284 }
285
286 const char *CYDeclaration::ForEachIn() const {
287 return identifier_->Value();
288 }
289
290 void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
291 if ((flags & CYNoLeader) != 0)
292 out << ' ';
293 out << "var";
294 Output(out, CYRight(flags) | CYNoLeader);
295 }
296
297 void CYDeclaration::ForEachIn(CYOutput &out) const {
298 out << *identifier_;
299 }
300
301 void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
302 if ((flags & CYNoLeader) != 0)
303 out << ' ';
304 out << *identifier_;
305 if (initialiser_ != NULL) {
306 if (out.pretty_)
307 out << ' ';
308 out << '=';
309 if (out.pretty_)
310 out << ' ';
311 initialiser_->Output(out, CYPA, CYRight(flags));
312 } else if ((flags & CYNoTrailer) != 0)
313 out << ' ';
314 }
315
316 void CYDeclarations::For(CYOutput &out) const {
317 out << "var";
318 Output(out, CYNoIn | CYNoLeader);
319 }
320
321 void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
322 const CYDeclarations *declaration(this);
323 bool first(true);
324 output:
325 CYDeclarations *next(declaration->next_);
326 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
327 first = false;
328 declaration->declaration_->Output(out, jacks);
329
330 if (next != NULL) {
331 out << ',';
332 if (out.pretty_)
333 out << ' ';
334 declaration = next;
335 goto output;
336 }
337 }
338
339 void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
340 object_->Output(out, Precedence(), CYLeft(flags));
341 if (const char *word = property_->Word())
342 out << '.' << word;
343 else {
344 out << '[';
345 property_->Output(out, CYNoFlags);
346 out << ']';
347 }
348 }
349
350 void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
351 if ((flags & CYNoLeader) != 0)
352 out << ' ';
353 out << "do";
354 code_->Single(out, CYNoLeader | CYNoTrailer);
355 out << "while";
356 if (out.pretty_)
357 out << ' ';
358 out << '(';
359 test_->Output(out, CYNoFlags);
360 out << ')';
361 }
362
363 void CYElement::Output(CYOutput &out) const {
364 if (value_ != NULL)
365 value_->Output(out, CYPA, CYNoFlags);
366 if (next_ != NULL || value_ == NULL) {
367 out << ',';
368 if (out.pretty_ && next_ != NULL && next_->value_ != NULL)
369 out << ' ';
370 }
371 if (next_ != NULL)
372 next_->Output(out);
373 }
374
375 void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
376 out << ';';
377 }
378
379 void CYExpress::Output(CYOutput &out, CYFlags flags) const {
380 bool terminator((flags & CYNoTerminator) == 0);
381 expression_->Output(out, (terminator ? CYLeft(flags) : flags) | CYNoBF);
382 if (terminator)
383 out << ';';
384 }
385
386 void CYExpression::ClassName(CYOutput &out, bool object) const {
387 Output(out, CYPA, CYNoFlags);
388 }
389
390 const char *CYExpression::ForEachIn() const {
391 return NULL;
392 }
393
394 void CYExpression::For(CYOutput &out) const {
395 Output(out, CYNoIn);
396 }
397
398 void CYExpression::ForEachIn(CYOutput &out) const {
399 Output(out, CYPA, CYNoRightHand);
400 }
401
402 void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
403 Output(out, flags | CYNoRightHand);
404 }
405
406 void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
407 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand()) {
408 out << '(';
409 Output(out, CYNoFlags);
410 out << ')';
411 } else
412 Output(out, flags);
413 }
414
415 void CYField::Output(CYOutput &out) const {
416 // XXX: implement!
417 }
418
419 void CYFinally::Output(CYOutput &out) const {
420 out << "finally";
421 if (out.pretty_)
422 out << ' ';
423 out << '{';
424 if (code_ != NULL)
425 code_->Multiple(out);
426 out << '}';
427 }
428
429 void CYFor::Output(CYOutput &out, CYFlags flags) const {
430 if ((flags & CYNoLeader) != 0)
431 out << ' ';
432 out << "for";
433 if (out.pretty_)
434 out << ' ';
435 out << '(';
436 if (initialiser_ != NULL)
437 initialiser_->For(out);
438 out << ';';
439 if (test_ != NULL)
440 test_->Output(out, CYNoFlags);
441 out << ';';
442 if (increment_ != NULL)
443 increment_->Output(out, CYNoFlags);
444 out << ')';
445 code_->Single(out, CYNoFlags);
446 }
447
448 void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
449 if ((flags & CYNoLeader) != 0)
450 out << ' ';
451
452 out << "with({$cys:0,$cyt:0}){";
453
454 out << "$cys=";
455 set_->Output(out, CYPA, CYNoFlags);
456 out << ';';
457
458 out << "for($cyt in $cys){";
459
460 initialiser_->ForEachIn(out);
461 out << "=$cys[$cyt];";
462
463 code_->Multiple(out);
464
465 out << '}';
466
467 out << '}';
468 }
469
470 void CYForEachInComprehension::Begin_(CYOutput &out) const {
471 out << "(function($cys){";
472 out << "$cys=";
473 set_->Output(out, CYPA, CYNoFlags);
474 out << ';';
475
476 out << "for(" << *name_ << " in $cys){";
477 out << *name_ << "=$cys[" << *name_ << "];";
478 }
479
480 void CYForEachInComprehension::End_(CYOutput &out) const {
481 out << "}}());";
482 }
483
484 void CYForIn::Output(CYOutput &out, CYFlags flags) const {
485 if ((flags & CYNoLeader) != 0)
486 out << ' ';
487 out << "for";
488 if (out.pretty_)
489 out << ' ';
490 out << '(';
491 initialiser_->ForIn(out, CYNoIn | CYNoTrailer);
492 out << "in";
493 set_->Output(out, CYNoLeader);
494 out << ')';
495 code_->Single(out, CYRight(flags));
496 }
497
498 void CYForInComprehension::Begin_(CYOutput &out) const {
499 out << "for";
500 if (out.pretty_)
501 out << ' ';
502 out << '(' << *name_ << " in";
503 set_->Output(out, CYNoLeader);
504 out << ')';
505 }
506
507 void CYFunction::Output(CYOutput &out, CYFlags flags) const {
508 bool protect((flags & CYNoFunction) != 0);
509 if (protect)
510 out << '(';
511 else if ((flags & CYNoLeader) != 0)
512 out << ' ';
513 out << "function";
514 if (name_ != NULL)
515 out << ' ' << *name_;
516 out << '(';
517 if (parameters_ != NULL)
518 out << *parameters_;
519 out << ')';
520 OutputBody(out, body_);
521 if (protect)
522 out << ')';
523 }
524
525 void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
526 CYFunction::Output(out, flags);
527 }
528
529 void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
530 CYFunction::Output(out, flags);
531 }
532
533 void CYFunctionParameter::Output(CYOutput &out) const {
534 out << *name_;
535 if (next_ != NULL) {
536 out << ',';
537 if (out.pretty_)
538 out << ' ';
539 out << *next_;
540 }
541 }
542
543 void CYIf::Output(CYOutput &out, CYFlags flags) const {
544 bool protect(false);
545 if (false_ == NULL && (flags & CYNoDangle) != 0) {
546 protect = true;
547 out << '{';
548 } else if ((flags & CYNoLeader) != 0)
549 out << ' ';
550 out << "if";
551 if (out.pretty_)
552 out << ' ';
553 out << '(';
554 test_->Output(out, CYNoFlags);
555 out << ')';
556 CYFlags right(protect ? CYNoFlags : CYRight(flags));
557 CYFlags jacks(CYNoDangle);
558 jacks |= false_ == NULL ? right : CYNoTrailer;
559 true_->Single(out, jacks);
560 if (false_ != NULL) {
561 out << "else";
562 if (protect)
563 right |= CYNoTerminator;
564 false_->Single(out, CYNoLeader | right);
565 }
566 if (protect)
567 out << '}';
568 }
569
570 void CYIfComprehension::Begin_(CYOutput &out) const {
571 out << "if(";
572 test_->Output(out, CYNoFlags);
573 out << ')';
574 }
575
576 void CYIndirect::Output(CYOutput &out, CYFlags flags) const {
577 rhs_->Output(out, 1, CYLeft(flags));
578 out << ".$cyi";
579 if ((flags & CYNoTrailer) != 0)
580 out << ' ';
581 }
582
583 void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
584 object_->Output(out, Precedence(), CYLeft(flags));
585 out << ".$cyi";
586 if (const char *word = property_->Word())
587 out << '.' << word;
588 else {
589 out << '[';
590 property_->Output(out, CYNoFlags);
591 out << ']';
592 }
593 }
594
595 void CYInfix::Output(CYOutput &out, CYFlags flags) const {
596 const char *name(Operator());
597 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in"));
598 if (protect)
599 out << '(';
600 bool alphabetic(Alphabetic());
601 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
602 if (alphabetic)
603 left |= CYNoTrailer;
604 lhs_->Output(out, Precedence(), left);
605 if (out.pretty_)
606 out << ' ';
607 out << name;
608 if (out.pretty_)
609 out << ' ';
610 CYFlags right(protect ? CYNoFlags : CYRight(flags));
611 if (alphabetic)
612 right |= CYNoLeader;
613 if (strcmp(name, "-") == 0)
614 right |= CYNoHyphen;
615 rhs_->Output(out, Precedence() - 1, right);
616 if (protect)
617 out << ')';
618 }
619
620 void CYLet::Output(CYOutput &out, CYFlags flags) const {
621 if ((flags & CYNoLeader) != 0)
622 out << ' ';
623 out << "let";
624 if (out.pretty_)
625 out << ' ';
626 out << '(';
627 declarations_->Output(out, CYNoFlags);
628 out << ')';
629 if (out.pretty_)
630 out << ' ';
631 out << '{';
632 if (statements_ != NULL)
633 statements_->Multiple(out);
634 out << '}';
635 }
636
637 void CYMessage::Output(CYOutput &out, bool replace) const {
638 if (next_ != NULL)
639 next_->Output(out, replace);
640 out << "$cyn=new Selector(\"";
641 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
642 if (parameter->tag_ != NULL) {
643 out << *parameter->tag_;
644 if (parameter->name_ != NULL)
645 out << ':';
646 }
647 out << "\");";
648 out << "$cyt=$cyn.type($cy" << (instance_ ? 's' : 'p') << ");";
649 out << "class_" << (replace ? "replace" : "add") << "Method($cy" << (instance_ ? 'c' : 'm') << ",$cyn,";
650 out << "new Functor(function(self,_cmd";
651 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
652 if (parameter->name_ != NULL)
653 out << ',' << *parameter->name_;
654 out << "){return function(){";
655 if (body_ != NULL)
656 body_->Multiple(out);
657 out << "}.call(self);},$cyt),$cyt);";
658 }
659
660 void CYNew::Output(CYOutput &out, CYFlags flags) const {
661 if ((flags & CYNoLeader) != 0)
662 out << ' ';
663 out << "new";
664 if (out.pretty_)
665 out << ' ';
666 CYFlags jacks(CYNoCall | CYCenter(flags));
667 if (!out.pretty_)
668 jacks |= CYNoLeader;
669 constructor_->Output(out, Precedence(), jacks);
670 if (arguments_ != NULL) {
671 out << '(';
672 arguments_->Output(out);
673 out << ')';
674 }
675 }
676
677 void CYNull::Output(CYOutput &out, CYFlags flags) const {
678 if ((flags & CYNoLeader) != 0)
679 out << ' ';
680 CYWord::Output(out);
681 if ((flags & CYNoTrailer) != 0)
682 out << ' ';
683 }
684
685 void CYNumber::Output(CYOutput &out, CYFlags flags) const {
686 double value(Value());
687 if ((flags & CYNoLeader) != 0 || value < 0 && (flags & CYNoHyphen) != 0)
688 out << ' ';
689 // XXX: decide on correct precision
690 out.out_ << std::setprecision(9) << value;
691 if ((flags & CYNoTrailer) != 0)
692 out << ' ';
693 }
694
695 void CYNumber::PropertyName(CYOutput &out) const {
696 Output(out, CYNoFlags);
697 }
698
699 void CYObject::Output(CYOutput &out, CYFlags flags) const {
700 bool protect((flags & CYNoBrace) != 0);
701 if (protect)
702 out << '(';
703 out << '{';
704 if (property_ != NULL)
705 property_->Output(out);
706 out << '}';
707 if (protect)
708 out << ')';
709 }
710
711 void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
712 lhs_->Output(out, Precedence(), CYLeft(flags));
713 out << Operator();
714 }
715
716 void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
717 const char *name(Operator());
718 bool alphabetic(Alphabetic());
719 if (alphabetic && (flags & CYNoLeader) != 0 || name[0] == '-' && (flags & CYNoHyphen) != 0)
720 out << ' ';
721 out << name;
722 if (alphabetic && out.pretty_)
723 out << ' ';
724 CYFlags right(CYRight(flags));
725 if (alphabetic)
726 right |= CYNoLeader;
727 rhs_->Output(out, Precedence(), right);
728 }
729
730 void CYProperty::Output(CYOutput &out) const {
731 name_->PropertyName(out);
732 out << ':';
733 if (out.pretty_)
734 out << ' ';
735 value_->Output(out, CYPA, CYNoFlags);
736 if (next_ != NULL) {
737 out << ',';
738 if (out.pretty_)
739 out << ' ';
740 next_->Output(out);
741 }
742 }
743
744 void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
745 out << Value();
746 if ((flags & CYNoTrailer) != 0)
747 out << ' ';
748 }
749
750 void CYReturn::Output(CYOutput &out, CYFlags flags) const {
751 bool terminator((flags & CYNoTerminator) == 0);
752 if ((flags & CYNoLeader) != 0)
753 out << ' ';
754 out << "return";
755 if (value_ != NULL)
756 value_->Output(out, (terminator ? CYCenter(flags) : flags) | CYNoLeader);
757 if (terminator)
758 out << ';';
759 }
760
761 void CYSelector::Output(CYOutput &out, CYFlags flags) const {
762 if ((flags & CYNoLeader) != 0)
763 out << ' ';
764 out << "new Selector(\"";
765 if (name_ != NULL)
766 name_->Output(out);
767 out << "\")";
768 }
769
770 void CYSelectorPart::Output(CYOutput &out) const {
771 if (name_ != NULL)
772 out << *name_;
773 if (value_)
774 out << ':';
775 if (next_ != NULL)
776 next_->Output(out);
777 }
778
779 void CYSend::Output(CYOutput &out, CYFlags flags) const {
780 if ((flags & CYNoLeader) != 0)
781 out << ' ';
782 out << "objc_msgSend(";
783 self_->Output(out, CYPA, CYNoFlags);
784 out << ',';
785 std::ostringstream name;
786 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
787 if (argument->name_ != NULL) {
788 name << *argument->name_;
789 if (argument->value_ != NULL)
790 name << ':';
791 }
792 out.out_ << reinterpret_cast<void *>(sel_registerName(name.str().c_str()));
793 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
794 if (argument->value_ != NULL) {
795 out << ',';
796 argument->value_->Output(out, CYPA, CYNoFlags);
797 }
798 out << ')';
799 }
800
801 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
802 bool first(true);
803 for (const CYStatement *next(this); next != NULL; next = next->next_) {
804 bool last(next->next_ == NULL);
805 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
806 if (last)
807 jacks |= CYNoTerminator;
808 first = false;
809 out.Indent();
810 next->Output(out, jacks);
811 if (out.pretty_)
812 out << '\n';
813 }
814 }
815
816 void CYStatement::Single(CYOutput &out, CYFlags flags) const {
817 if (next_ != NULL) {
818 if (out.pretty_)
819 out << ' ';
820 out << '{';
821 if (out.pretty_)
822 out << '\n';
823 ++out.indent_;
824 Multiple(out);
825 --out.indent_;
826 out.Indent();
827 out << '}';
828 } else {
829 if (out.pretty_)
830 out << '\n';
831 bool protect(false);
832 if (labels_ != NULL && (flags & CYNoLeader) != 0)
833 protect = true;
834 if (protect)
835 out << ' ';
836 for (CYLabel *label(labels_); label != NULL; label = label->next_) {
837 out << *label->name_ << ':';
838 if (out.pretty_)
839 out << ' ';
840 }
841 ++out.indent_;
842 out.Indent();
843 Output(out, protect ? CYRight(flags) : flags);
844 --out.indent_;
845 if (out.pretty_)
846 out << '\n';
847 }
848 }
849
850 void CYString::Output(CYOutput &out, CYFlags flags) const {
851 unsigned quot(0), apos(0);
852 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
853 if (*value == '"')
854 ++quot;
855 else if (*value == '\'')
856 ++apos;
857
858 bool single(quot > apos);
859
860 out << (single ? '\'' : '"');
861 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
862 switch (*value) {
863 case '\\': out << "\\\\"; break;
864 case '\b': out << "\\b"; break;
865 case '\f': out << "\\f"; break;
866 case '\n': out << "\\n"; break;
867 case '\r': out << "\\r"; break;
868 case '\t': out << "\\t"; break;
869 case '\v': out << "\\v"; break;
870
871 case '"':
872 if (!single)
873 out << "\\\"";
874 else goto simple;
875 break;
876
877 case '\'':
878 if (single)
879 out << "\\'";
880 else goto simple;
881 break;
882
883 default:
884 if (*value < 0x20 || *value >= 0x7f)
885 out.out_ << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value);
886 else simple:
887 out << *value;
888 }
889 out << (single ? '\'' : '"');
890 }
891
892 void CYString::PropertyName(CYOutput &out) const {
893 if (const char *word = Word())
894 out << word;
895 else
896 Output(out, CYNoFlags);
897 }
898
899 const char *CYString::Word() const {
900 if (size_ == 0 || !WordStartRange_[value_[0]])
901 return NULL;
902 for (size_t i(1); i != size_; ++i)
903 if (!WordEndRange_[value_[i]])
904 return NULL;
905 const char *value(Value());
906 // XXX: we should probably include the full ECMAScript3+5 list.
907 static const char *reserveds[] = {"class", "const", "enum", "export", "extends", "import", "super", NULL};
908 for (const char **reserved(reserveds); *reserved != NULL; ++reserved)
909 if (strcmp(*reserved, value) == 0)
910 return NULL;
911 return value;
912 }
913
914 void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
915 if ((flags & CYNoLeader) != 0)
916 out << ' ';
917 out << "switch";
918 if (out.pretty_)
919 out << ' ';
920 out << '(';
921 value_->Output(out, CYNoFlags);
922 out << ')';
923 if (out.pretty_)
924 out << ' ';
925 out << '{';
926 if (clauses_ != NULL)
927 out << *clauses_;
928 out << '}';
929 }
930
931 void CYThis::Output(CYOutput &out, CYFlags flags) const {
932 if ((flags & CYNoLeader) != 0)
933 out << ' ';
934 CYWord::Output(out);
935 if ((flags & CYNoTrailer) != 0)
936 out << ' ';
937 }
938
939 void CYThrow::Output(CYOutput &out, CYFlags flags) const {
940 bool terminator((flags & CYNoTerminator) == 0);
941 if ((flags & CYNoLeader) != 0)
942 out << ' ';
943 out << "throw";
944 if (value_ != NULL)
945 value_->Output(out, (terminator ? CYCenter(flags) : flags) | CYNoLeader);
946 if (terminator)
947 out << ';';
948 }
949
950 void CYTry::Output(CYOutput &out, CYFlags flags) const {
951 if ((flags & CYNoLeader) != 0)
952 out << ' ';
953 out << "try";
954 if (out.pretty_)
955 out << ' ';
956 out << '{';
957 if (code_ != NULL)
958 code_->Multiple(out);
959 out << '}';
960 if (catch_ != NULL)
961 catch_->Output(out);
962 if (finally_ != NULL)
963 finally_->Output(out);
964 }
965
966 void CYVar::Output(CYOutput &out, CYFlags flags) const {
967 bool terminator((flags & CYNoTerminator) == 0);
968 if ((flags & CYNoLeader) != 0)
969 out << ' ';
970 out << "var";
971 declarations_->Output(out, (terminator ? CYCenter(flags) : flags) | CYNoLeader);
972 if (terminator)
973 out << ';';
974 }
975
976 void CYVariable::Output(CYOutput &out, CYFlags flags) const {
977 if ((flags & CYNoLeader) != 0)
978 out << ' ';
979 out << *name_;
980 if ((flags & CYNoTrailer) != 0)
981 out << ' ';
982 }
983
984 void CYWhile::Output(CYOutput &out, CYFlags flags) const {
985 if ((flags & CYNoLeader) != 0)
986 out << ' ';
987 out << "while(";
988 test_->Output(out, CYNoFlags);
989 out << ')';
990 code_->Single(out, CYRight(flags));
991 }
992
993 void CYWith::Output(CYOutput &out, CYFlags flags) const {
994 if ((flags & CYNoLeader) != 0)
995 out << ' ';
996 out << "with(";
997 scope_->Output(out, CYNoFlags);
998 out << ')';
999 code_->Single(out, CYRight(flags));
1000 }
1001
1002 void CYWord::ClassName(CYOutput &out, bool object) const {
1003 if (object)
1004 out << "objc_getClass(";
1005 out << '"' << Value() << '"';
1006 if (object)
1007 out << ')';
1008 }
1009
1010 void CYWord::Output(CYOutput &out) const {
1011 out << Value();
1012 }
1013
1014 void CYWord::PropertyName(CYOutput &out) const {
1015 Output(out);
1016 }