]> git.saurik.com Git - cycript.git/blob - Output.cpp
Add a local install target (why not?) to xcode.mk.
[cycript.git] / Output.cpp
1 /* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2013 Jay Freeman (saurik)
3 */
4
5 /* GNU General Public License, Version 3 {{{ */
6 /*
7 * Cycript is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation, either version 3 of the License,
10 * or (at your option) any later version.
11 *
12 * Cycript is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Cycript. If not, see <http://www.gnu.org/licenses/>.
19 **/
20 /* }}} */
21
22 #include "cycript.hpp"
23 #include "Parser.hpp"
24
25 #include <sstream>
26
27 void CYOutput::Terminate() {
28 out_ << ';';
29 mode_ = NoMode;
30 }
31
32 CYOutput &CYOutput::operator <<(char rhs) {
33 if (rhs == ' ' || rhs == '\n')
34 if (pretty_)
35 out_ << rhs;
36 else goto done;
37 else if (rhs == '\t')
38 if (pretty_)
39 for (unsigned i(0); i != indent_; ++i)
40 out_ << " ";
41 else goto done;
42 else if (rhs == '\r') {
43 if (right_) {
44 out_ << '\n';
45 right_ = false;
46 } goto done;
47 } else goto work;
48
49 right_ = true;
50 mode_ = NoMode;
51 goto done;
52
53 work:
54 if (mode_ == Terminated && rhs != '}') {
55 right_ = true;
56 out_ << ';';
57 }
58
59 if (rhs == ';') {
60 if (pretty_)
61 goto none;
62 else {
63 mode_ = Terminated;
64 goto done;
65 }
66 } else if (rhs == '+') {
67 if (mode_ == NoPlus)
68 out_ << ' ';
69 mode_ = NoPlus;
70 } else if (rhs == '-') {
71 if (mode_ == NoHyphen)
72 out_ << ' ';
73 mode_ = NoHyphen;
74 } else if (WordEndRange_[rhs]) {
75 if (mode_ == NoLetter)
76 out_ << ' ';
77 mode_ = NoLetter;
78 } else none:
79 mode_ = NoMode;
80
81 right_ = true;
82 out_ << rhs;
83 done:
84 return *this;
85 }
86
87 CYOutput &CYOutput::operator <<(const char *rhs) {
88 size_t size(strlen(rhs));
89
90 if (size == 1)
91 return *this << *rhs;
92
93 if (mode_ == Terminated)
94 out_ << ';';
95 else if (
96 mode_ == NoPlus && *rhs == '+' ||
97 mode_ == NoHyphen && *rhs == '-' ||
98 mode_ == NoLetter && WordEndRange_[*rhs]
99 )
100 out_ << ' ';
101
102 if (WordEndRange_[rhs[size - 1]])
103 mode_ = NoLetter;
104 else
105 mode_ = NoMode;
106
107 right_ = true;
108 out_ << rhs;
109 return *this;
110 }
111
112 void CYArgument::Output(CYOutput &out) const {
113 if (name_ != NULL) {
114 out << *name_;
115 if (value_ != NULL)
116 out << ':' << ' ';
117 }
118 if (value_ != NULL)
119 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
120 if (next_ != NULL) {
121 if (next_->name_ == NULL)
122 out << ',';
123 out << ' ' << *next_;
124 }
125 }
126
127 void CYArray::Output(CYOutput &out, CYFlags flags) const {
128 out << '[' << elements_ << ']';
129 }
130
131 void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
132 out << '[' << *expression_ << ' ' << *comprehensions_ << ']';
133 }
134
135 void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
136 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
137 out << ' ' << Operator() << ' ';
138 rhs_->Output(out, Precedence(), CYRight(flags));
139 }
140
141 void CYBlock::Output(CYOutput &out) const {
142 out << '{' << '\n';
143 ++out.indent_;
144 if (statements_ != NULL)
145 statements_->Multiple(out);
146 --out.indent_;
147 out << '\t' << '}';
148 }
149
150 void CYBlock::Output(CYOutput &out, CYFlags flags) const {
151 if (statements_ == NULL)
152 out.Terminate();
153 else if (statements_->next_ == NULL)
154 statements_->Single(out, flags);
155 else
156 Output(out);
157 }
158
159 void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
160 out << (Value() ? "true" : "false");
161 }
162
163 void CYBreak::Output(CYOutput &out, CYFlags flags) const {
164 out << "break";
165 if (label_ != NULL)
166 out << ' ' << *label_;
167 out << ';';
168 }
169
170 void CYCall::Output(CYOutput &out, CYFlags flags) const {
171 bool protect((flags & CYNoCall) != 0);
172 if (protect)
173 out << '(';
174 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
175 out << '(' << arguments_ << ')';
176 if (protect)
177 out << ')';
178 }
179
180 namespace cy {
181 namespace Syntax {
182
183 void Catch::Output(CYOutput &out) const {
184 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ' << code_;
185 }
186
187 } }
188
189 void CYComment::Output(CYOutput &out, CYFlags flags) const {
190 out << '\r';
191 out.out_ << value_;
192 out.right_ = true;
193 out << '\r';
194 }
195
196 void CYCompound::Output(CYOutput &out, CYFlags flags) const {
197 if (next_ == NULL)
198 expression_->Output(out, flags);
199 else {
200 expression_->Output(out, CYLeft(flags));
201 out << ',' << ' ';
202 next_->Output(out, CYRight(flags));
203 }
204 }
205
206 void CYCondition::Output(CYOutput &out, CYFlags flags) const {
207 test_->Output(out, Precedence() - 1, CYLeft(flags));
208 out << ' ' << '?' << ' ';
209 if (true_ != NULL)
210 true_->Output(out, CYAssign::Precedence_, CYNoFlags);
211 out << ' ' << ':' << ' ';
212 false_->Output(out, CYAssign::Precedence_, CYRight(flags));
213 }
214
215 void CYContinue::Output(CYOutput &out, CYFlags flags) const {
216 out << "continue";
217 if (label_ != NULL)
218 out << ' ' << *label_;
219 out << ';';
220 }
221
222 void CYClause::Output(CYOutput &out) const {
223 if (case_ != NULL)
224 out << "case" << ' ' << *case_;
225 else
226 out << "default";
227 out << ':' << '\n';
228 if (statements_ != NULL)
229 statements_->Multiple(out);
230 out << next_;
231 }
232
233 void CYDebugger::Output(CYOutput &out, CYFlags flags) const {
234 out << "debugger" << ';';
235 }
236
237 void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
238 out << "var";
239 Output(out, CYRight(flags));
240 }
241
242 void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
243 out << *identifier_;
244 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
245 if (initialiser_ != NULL) {
246 out << ' ' << '=' << ' ';
247 initialiser_->Output(out, CYAssign::Precedence_, CYRight(flags));
248 }
249 }
250
251 void CYForDeclarations::Output(CYOutput &out, CYFlags flags) const {
252 out << "var";
253 Output(out, CYRight(flags));
254 }
255
256 void CYDeclarations::Output(CYOutput &out) const {
257 Output(out, CYNoFlags);
258 }
259
260 void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
261 const CYDeclarations *declaration(this);
262 bool first(true);
263
264 for (;;) {
265 CYDeclarations *next(declaration->next_);
266
267 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
268 first = false;
269 declaration->declaration_->Output(out, jacks);
270
271 if (next == NULL)
272 break;
273
274 out << ',' << ' ';
275 declaration = next;
276 }
277 }
278
279 void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
280 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
281 if (const char *word = property_->Word())
282 out << '.' << word;
283 else
284 out << '[' << *property_ << ']';
285 }
286
287 void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
288 out << "do";
289 code_->Single(out, CYCenter(flags));
290 out << "while" << ' ' << '(' << *test_ << ')';
291 }
292
293 void CYElement::Output(CYOutput &out) const {
294 if (value_ != NULL)
295 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
296 if (next_ != NULL || value_ == NULL) {
297 out << ',';
298 if (next_ != NULL && next_->value_ != NULL)
299 out << ' ';
300 }
301 if (next_ != NULL)
302 next_->Output(out);
303 }
304
305 void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
306 out.Terminate();
307 }
308
309 void CYExpress::Output(CYOutput &out, CYFlags flags) const {
310 expression_->Output(out, flags | CYNoBF);
311 out << ';';
312 }
313
314 void CYExpression::ClassName(CYOutput &out, bool object) const {
315 Output(out, CYAssign::Precedence_, CYNoFlags);
316 }
317
318 void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
319 Output(out, flags | CYNoRightHand);
320 }
321
322 void CYExpression::Output(CYOutput &out) const {
323 Output(out, CYNoFlags);
324 }
325
326 void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const {
327 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
328 out << '(' << *this << ')';
329 else
330 Output(out, flags);
331 }
332
333 void CYFatArrow::Output(CYOutput &out, CYFlags flags) const {
334 out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << code_;
335 }
336
337 void CYFinally::Output(CYOutput &out) const {
338 out << ' ' << "finally" << ' ' << code_;
339 }
340
341 void CYFor::Output(CYOutput &out, CYFlags flags) const {
342 out << "for" << ' ' << '(';
343 if (initialiser_ != NULL)
344 initialiser_->Output(out, CYNoIn);
345 out.Terminate();
346 if (test_ != NULL)
347 out << ' ';
348 out << test_;
349 out.Terminate();
350 if (increment_ != NULL)
351 out << ' ';
352 out << increment_;
353 out << ')';
354 code_->Single(out, CYRight(flags));
355 }
356
357 void CYForOf::Output(CYOutput &out, CYFlags flags) const {
358 out << "for" << ' ' << "each" << ' ' << '(';
359 initialiser_->ForIn(out, CYNoIn);
360 out << "in" << *set_ << ')';
361 code_->Single(out, CYRight(flags));
362 }
363
364 void CYForOfComprehension::Output(CYOutput &out) const {
365 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
366 }
367
368 void CYForIn::Output(CYOutput &out, CYFlags flags) const {
369 out << "for" << ' ' << '(';
370 if (initialiser_ != NULL)
371 initialiser_->ForIn(out, CYNoIn);
372 out << "in" << *set_ << ')';
373 code_->Single(out, CYRight(flags));
374 }
375
376 void CYForInComprehension::Output(CYOutput &out) const {
377 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
378 }
379
380 void CYFunction::Output(CYOutput &out, CYFlags flags) const {
381 // XXX: one could imagine using + here to save a byte
382 bool protect((flags & CYNoFunction) != 0);
383 if (protect)
384 out << '(';
385 out << "function";
386 if (name_ != NULL)
387 out << ' ' << *name_;
388 out << '(' << parameters_ << ')';
389 out << ' ' << code_;
390 if (protect)
391 out << ')';
392 }
393
394 void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
395 CYFunction::Output(out, flags);
396 }
397
398 void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
399 CYFunction::Output(out, flags);
400 }
401
402 void CYFunctionParameter::Output(CYOutput &out) const {
403 initialiser_->Output(out, CYNoFlags);
404 if (next_ != NULL)
405 out << ',' << ' ' << *next_;
406 }
407
408 const char *CYIdentifier::Word() const {
409 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
410 }
411
412 void CYIf::Output(CYOutput &out, CYFlags flags) const {
413 bool protect(false);
414 if (false_ == NULL && (flags & CYNoDangle) != 0) {
415 protect = true;
416 out << '{';
417 }
418
419 out << "if" << ' ' << '(' << *test_ << ')';
420
421 CYFlags right(protect ? CYNoFlags : CYRight(flags));
422
423 CYFlags jacks(CYNoDangle);
424 if (false_ == NULL)
425 jacks |= right;
426 else
427 jacks |= protect ? CYNoFlags : CYCenter(flags);
428
429 true_->Single(out, jacks);
430
431 if (false_ != NULL) {
432 out << '\t' << "else";
433 false_->Single(out, right);
434 }
435
436 if (protect)
437 out << '}';
438 }
439
440 void CYIfComprehension::Output(CYOutput &out) const {
441 out << "if" << ' ' << '(' << *test_ << ')' << next_;
442 }
443
444 void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
445 object_->Output(out, Precedence(), CYLeft(flags));
446 if (const char *word = property_->Word())
447 out << "->" << word;
448 else
449 out << "->" << '[' << *property_ << ']';
450 }
451
452 void CYInfix::Output(CYOutput &out, CYFlags flags) const {
453 const char *name(Operator());
454 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
455 if (protect)
456 out << '(';
457 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
458 lhs_->Output(out, Precedence(), left);
459 out << ' ' << name << ' ';
460 CYFlags right(protect ? CYNoFlags : CYRight(flags));
461 rhs_->Output(out, Precedence() - 1, right);
462 if (protect)
463 out << ')';
464 }
465
466 void CYLabel::Output(CYOutput &out, CYFlags flags) const {
467 out << *name_ << ':' << ' ';
468 statement_->Single(out, CYRight(flags));
469 }
470
471 void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
472 next_->Output(out, Precedence(), identifier);
473 out << '[';
474 out << size_;
475 out << ']';
476 }
477
478 void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
479 out << '(' << '^';
480 next_->Output(out, Precedence(), identifier);
481 out << ')' << '(' << parameters_ << ')';
482 }
483
484 void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
485 out << "const";
486 next_->Output(out, Precedence(), identifier);
487 }
488
489 void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
490 next_->Output(out, Precedence(), identifier);
491 out << '(' << parameters_ << ')';
492 }
493
494 void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
495 out << '*';
496 next_->Output(out, Precedence(), identifier);
497 }
498
499 void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
500 out << "volatile";
501 next_->Output(out, Precedence(), identifier);
502 }
503
504 void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
505 if (this == NULL) {
506 out << identifier;
507 return;
508 }
509
510 bool protect(precedence > Precedence());
511
512 if (protect)
513 out << '(';
514 Output(out, identifier);
515 if (protect)
516 out << ')';
517 }
518
519 void CYTypedIdentifier::Output(CYOutput &out) const {
520 specifier_->Output(out);
521 modifier_->Output(out, 0, identifier_);
522 }
523
524 void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
525 out << "@encode(" << typed_ << ")";
526 }
527
528 void CYTypedParameter::Output(CYOutput &out) const {
529 out << typed_;
530 if (next_ != NULL)
531 out << ',' << ' ' << next_;
532 }
533
534 void CYLambda::Output(CYOutput &out, CYFlags flags) const {
535 // XXX: this is seriously wrong
536 out << "[](";
537 out << ")->";
538 out << "{";
539 out << "}";
540 }
541
542 void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
543 out << "typedef" << *typed_;
544 }
545
546 void CYLetStatement::Output(CYOutput &out, CYFlags flags) const {
547 out << "let" << ' ' << '(' << *declarations_ << ')';
548 code_->Single(out, CYRight(flags));
549 }
550
551 namespace cy {
552 namespace Syntax {
553
554 void New::Output(CYOutput &out, CYFlags flags) const {
555 out << "new" << ' ';
556 CYFlags jacks(CYNoCall | CYCenter(flags));
557 constructor_->Output(out, Precedence(), jacks);
558 if (arguments_ != NULL)
559 out << '(' << *arguments_ << ')';
560 }
561
562 } }
563
564 void CYNull::Output(CYOutput &out, CYFlags flags) const {
565 CYWord::Output(out);
566 }
567
568 void CYNumber::Output(CYOutput &out, CYFlags flags) const {
569 std::ostringstream str;
570 CYNumerify(str, Value());
571 std::string value(str.str());
572 out << value.c_str();
573 // XXX: this should probably also handle hex conversions and exponents
574 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
575 out << '.';
576 }
577
578 void CYNumber::PropertyName(CYOutput &out) const {
579 Output(out, CYNoFlags);
580 }
581
582 void CYObject::Output(CYOutput &out, CYFlags flags) const {
583 bool protect((flags & CYNoBrace) != 0);
584 if (protect)
585 out << '(';
586 out << '{' << '\n';
587 ++out.indent_;
588 out << properties_;
589 --out.indent_;
590 out << '\t' << '}';
591 if (protect)
592 out << ')';
593 }
594
595 void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
596 lhs_->Output(out, Precedence(), CYLeft(flags));
597 out << Operator();
598 }
599
600 void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
601 const char *name(Operator());
602 out << name;
603 if (Alphabetic())
604 out << ' ';
605 rhs_->Output(out, Precedence(), CYRight(flags));
606 }
607
608 void CYProgram::Output(CYOutput &out) const {
609 if (statements_ != NULL)
610 statements_->Multiple(out);
611 }
612
613 void CYProperty::Output(CYOutput &out) const {
614 out << '\t';
615 name_->PropertyName(out);
616 out << ':' << ' ';
617 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
618 if (next_ != NULL)
619 out << ',' << '\n' << *next_;
620 else
621 out << '\n';
622 }
623
624 void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
625 out << Value();
626 }
627
628 void CYReturn::Output(CYOutput &out, CYFlags flags) const {
629 out << "return";
630 if (value_ != NULL)
631 out << ' ' << *value_;
632 out << ';';
633 }
634
635 void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
636 call_->Output(out, CYLeft(flags));
637 out << ' ';
638 proc_->Output(out, CYRight(flags));
639 }
640
641 void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
642 // XXX: this is not outputting the parameters
643 out << code_;
644 }
645
646 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
647 bool first(true);
648 CYForEach (next, this) {
649 bool last(next->next_ == NULL);
650 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
651 first = false;
652 out << '\t';
653 next->Output(out, jacks);
654 out << '\n';
655 }
656 }
657
658 void CYStatement::Single(CYOutput &out, CYFlags flags) const {
659 if (this == NULL)
660 return out.Terminate();
661
662 _assert(next_ == NULL);
663 out << '\n';
664 ++out.indent_;
665 out << '\t';
666 Output(out, flags);
667 out << '\n';
668 --out.indent_;
669 }
670
671 void CYString::Output(CYOutput &out, CYFlags flags) const {
672 std::ostringstream str;
673 CYStringify(str, value_, size_);
674 out << str.str().c_str();
675 }
676
677 void CYString::PropertyName(CYOutput &out) const {
678 if (const char *word = Word())
679 out << word;
680 else
681 out << *this;
682 }
683
684 static const char *Reserved_[] = {
685 "false", "null", "true",
686
687 "break", "case", "catch", "continue", "default",
688 "delete", "do", "else", "finally", "for", "function",
689 "if", "in", "instanceof", "new", "return", "switch",
690 "this", "throw", "try", "typeof", "var", "void",
691 "while", "with",
692
693 "debugger", "const",
694
695 "class", "enum", "export", "extends", "import", "super",
696
697 "abstract", "boolean", "byte", "char", "double", "final",
698 "float", "goto", "int", "long", "native", "short",
699 "synchronized", "throws", "transient", "volatile",
700
701 "let", "yield",
702
703 NULL
704 };
705
706 const char *CYString::Word() const {
707 if (size_ == 0 || !WordStartRange_[value_[0]])
708 return NULL;
709 for (size_t i(1); i != size_; ++i)
710 if (!WordEndRange_[value_[i]])
711 return NULL;
712 const char *value(Value());
713 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
714 if (strcmp(*reserved, value) == 0)
715 return NULL;
716 return value;
717 }
718
719 void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
720 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
721 out << clauses_;
722 out << '}';
723 }
724
725 void CYThis::Output(CYOutput &out, CYFlags flags) const {
726 CYWord::Output(out);
727 }
728
729 namespace cy {
730 namespace Syntax {
731
732 void Throw::Output(CYOutput &out, CYFlags flags) const {
733 out << "throw";
734 if (value_ != NULL)
735 out << ' ' << *value_;
736 out << ';';
737 }
738
739 void Try::Output(CYOutput &out, CYFlags flags) const {
740 out << "try" << ' ' << code_ << catch_ << finally_;
741 }
742
743 } }
744
745 void CYTypeError::Output(CYOutput &out) const {
746 out << "@error";
747 }
748
749 void CYTypeLong::Output(CYOutput &out) const {
750 out << "long" << specifier_;
751 }
752
753 void CYTypeShort::Output(CYOutput &out) const {
754 out << "short" << specifier_;
755 }
756
757 void CYTypeSigned::Output(CYOutput &out) const {
758 out << "signed" << specifier_;
759 }
760
761 void CYTypeUnsigned::Output(CYOutput &out) const {
762 out << "unsigned" << specifier_;
763 }
764
765 void CYTypeVariable::Output(CYOutput &out) const {
766 out << *name_;
767 }
768
769 void CYTypeVoid::Output(CYOutput &out) const {
770 out << "void";
771 }
772
773 void CYVar::Output(CYOutput &out, CYFlags flags) const {
774 out << "var";
775 declarations_->Output(out, flags);
776 out << ';';
777 }
778
779 void CYVariable::Output(CYOutput &out, CYFlags flags) const {
780 out << *name_;
781 }
782
783 void CYWhile::Output(CYOutput &out, CYFlags flags) const {
784 out << "while" << '(' << *test_ << ')';
785 code_->Single(out, CYRight(flags));
786 }
787
788 void CYWith::Output(CYOutput &out, CYFlags flags) const {
789 out << "with" << '(' << *scope_ << ')';
790 code_->Single(out, CYRight(flags));
791 }
792
793 void CYWord::ClassName(CYOutput &out, bool object) const {
794 if (object)
795 out << "objc_getClass(";
796 out << '"' << Word() << '"';
797 if (object)
798 out << ')';
799 }
800
801 void CYWord::Output(CYOutput &out) const {
802 out << Word();
803 if (out.options_.verbose_)
804 out.out_ << '@' << this;
805 }
806
807 void CYWord::PropertyName(CYOutput &out) const {
808 Output(out);
809 }
810
811 const char *CYWord::Word() const {
812 return word_;
813 }