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