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