]> git.saurik.com Git - cycript.git/blob - Output.cpp
Manually unify CYLocal<CYPool>::key_ into Library.
[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 CYImport::Output(CYOutput &out, CYFlags flags) const {
444 out << "@import";
445 }
446
447 void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
448 object_->Output(out, Precedence(), CYLeft(flags));
449 if (const char *word = property_->Word())
450 out << "->" << word;
451 else
452 out << "->" << '[' << *property_ << ']';
453 }
454
455 void CYInfix::Output(CYOutput &out, CYFlags flags) const {
456 const char *name(Operator());
457 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
458 if (protect)
459 out << '(';
460 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
461 lhs_->Output(out, Precedence(), left);
462 out << ' ' << name << ' ';
463 CYFlags right(protect ? CYNoFlags : CYRight(flags));
464 rhs_->Output(out, Precedence() - 1, right);
465 if (protect)
466 out << ')';
467 }
468
469 void CYLabel::Output(CYOutput &out, CYFlags flags) const {
470 out << *name_ << ':' << ' ';
471 statement_->Single(out, CYRight(flags));
472 }
473
474 void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
475 next_->Output(out, Precedence(), identifier);
476 out << '[';
477 out << size_;
478 out << ']';
479 }
480
481 void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
482 out << '(' << '^';
483 next_->Output(out, Precedence(), identifier);
484 out << ')' << '(' << parameters_ << ')';
485 }
486
487 void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
488 out << "const";
489 next_->Output(out, Precedence(), identifier);
490 }
491
492 void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
493 next_->Output(out, Precedence(), identifier);
494 out << '(' << parameters_ << ')';
495 }
496
497 void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
498 out << '*';
499 next_->Output(out, Precedence(), identifier);
500 }
501
502 void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
503 out << "volatile";
504 next_->Output(out, Precedence(), identifier);
505 }
506
507 void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
508 if (this == NULL) {
509 out << identifier;
510 return;
511 }
512
513 bool protect(precedence > Precedence());
514
515 if (protect)
516 out << '(';
517 Output(out, identifier);
518 if (protect)
519 out << ')';
520 }
521
522 void CYTypedIdentifier::Output(CYOutput &out) const {
523 specifier_->Output(out);
524 modifier_->Output(out, 0, identifier_);
525 }
526
527 void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
528 out << "@encode(" << typed_ << ")";
529 }
530
531 void CYTypedParameter::Output(CYOutput &out) const {
532 out << typed_;
533 if (next_ != NULL)
534 out << ',' << ' ' << next_;
535 }
536
537 void CYLambda::Output(CYOutput &out, CYFlags flags) const {
538 // XXX: this is seriously wrong
539 out << "[](";
540 out << ")->";
541 out << "{";
542 out << "}";
543 }
544
545 void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
546 out << "typedef" << *typed_;
547 }
548
549 void CYLetStatement::Output(CYOutput &out, CYFlags flags) const {
550 out << "let" << ' ' << '(' << *declarations_ << ')';
551 code_->Single(out, CYRight(flags));
552 }
553
554 void CYModule::Output(CYOutput &out) const {
555 out << part_;
556 if (next_ != NULL)
557 out << '.' << next_;
558 }
559
560 namespace cy {
561 namespace Syntax {
562
563 void New::Output(CYOutput &out, CYFlags flags) const {
564 out << "new" << ' ';
565 CYFlags jacks(CYNoCall | CYCenter(flags));
566 constructor_->Output(out, Precedence(), jacks);
567 if (arguments_ != NULL)
568 out << '(' << *arguments_ << ')';
569 }
570
571 } }
572
573 void CYNull::Output(CYOutput &out, CYFlags flags) const {
574 CYWord::Output(out);
575 }
576
577 void CYNumber::Output(CYOutput &out, CYFlags flags) const {
578 std::ostringstream str;
579 CYNumerify(str, Value());
580 std::string value(str.str());
581 out << value.c_str();
582 // XXX: this should probably also handle hex conversions and exponents
583 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
584 out << '.';
585 }
586
587 void CYNumber::PropertyName(CYOutput &out) const {
588 Output(out, CYNoFlags);
589 }
590
591 void CYObject::Output(CYOutput &out, CYFlags flags) const {
592 bool protect((flags & CYNoBrace) != 0);
593 if (protect)
594 out << '(';
595 out << '{' << '\n';
596 ++out.indent_;
597 out << properties_;
598 --out.indent_;
599 out << '\t' << '}';
600 if (protect)
601 out << ')';
602 }
603
604 void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
605 lhs_->Output(out, Precedence(), CYLeft(flags));
606 out << Operator();
607 }
608
609 void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
610 const char *name(Operator());
611 out << name;
612 if (Alphabetic())
613 out << ' ';
614 rhs_->Output(out, Precedence(), CYRight(flags));
615 }
616
617 void CYProgram::Output(CYOutput &out) const {
618 if (statements_ != NULL)
619 statements_->Multiple(out);
620 }
621
622 void CYProperty::Output(CYOutput &out) const {
623 out << '\t';
624 name_->PropertyName(out);
625 out << ':' << ' ';
626 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
627 if (next_ != NULL)
628 out << ',' << '\n' << *next_;
629 else
630 out << '\n';
631 }
632
633 void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
634 out << Value();
635 }
636
637 void CYReturn::Output(CYOutput &out, CYFlags flags) const {
638 out << "return";
639 if (value_ != NULL)
640 out << ' ' << *value_;
641 out << ';';
642 }
643
644 void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
645 call_->Output(out, CYLeft(flags));
646 out << ' ';
647 proc_->Output(out, CYRight(flags));
648 }
649
650 void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
651 // XXX: this is not outputting the parameters
652 out << code_;
653 }
654
655 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
656 bool first(true);
657 CYForEach (next, this) {
658 bool last(next->next_ == NULL);
659 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
660 first = false;
661 out << '\t';
662 next->Output(out, jacks);
663 out << '\n';
664 }
665 }
666
667 void CYStatement::Single(CYOutput &out, CYFlags flags) const {
668 if (this == NULL)
669 return out.Terminate();
670
671 _assert(next_ == NULL);
672 out << '\n';
673 ++out.indent_;
674 out << '\t';
675 Output(out, flags);
676 out << '\n';
677 --out.indent_;
678 }
679
680 void CYString::Output(CYOutput &out, CYFlags flags) const {
681 std::ostringstream str;
682 CYStringify(str, value_, size_);
683 out << str.str().c_str();
684 }
685
686 void CYString::PropertyName(CYOutput &out) const {
687 if (const char *word = Word())
688 out << word;
689 else
690 out << *this;
691 }
692
693 static const char *Reserved_[] = {
694 "false", "null", "true",
695
696 "break", "case", "catch", "continue", "default",
697 "delete", "do", "else", "finally", "for", "function",
698 "if", "in", "instanceof", "new", "return", "switch",
699 "this", "throw", "try", "typeof", "var", "void",
700 "while", "with",
701
702 "debugger", "const",
703
704 "class", "enum", "export", "extends", "import", "super",
705
706 "abstract", "boolean", "byte", "char", "double", "final",
707 "float", "goto", "int", "long", "native", "short",
708 "synchronized", "throws", "transient", "volatile",
709
710 "let", "yield",
711
712 NULL
713 };
714
715 const char *CYString::Word() const {
716 if (size_ == 0 || !WordStartRange_[value_[0]])
717 return NULL;
718 for (size_t i(1); i != size_; ++i)
719 if (!WordEndRange_[value_[i]])
720 return NULL;
721 const char *value(Value());
722 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
723 if (strcmp(*reserved, value) == 0)
724 return NULL;
725 return value;
726 }
727
728 void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
729 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
730 out << clauses_;
731 out << '}';
732 }
733
734 void CYThis::Output(CYOutput &out, CYFlags flags) const {
735 CYWord::Output(out);
736 }
737
738 namespace cy {
739 namespace Syntax {
740
741 void Throw::Output(CYOutput &out, CYFlags flags) const {
742 out << "throw";
743 if (value_ != NULL)
744 out << ' ' << *value_;
745 out << ';';
746 }
747
748 void Try::Output(CYOutput &out, CYFlags flags) const {
749 out << "try" << ' ' << code_ << catch_ << finally_;
750 }
751
752 } }
753
754 void CYTypeError::Output(CYOutput &out) const {
755 out << "@error";
756 }
757
758 void CYTypeLong::Output(CYOutput &out) const {
759 out << "long" << specifier_;
760 }
761
762 void CYTypeShort::Output(CYOutput &out) const {
763 out << "short" << specifier_;
764 }
765
766 void CYTypeSigned::Output(CYOutput &out) const {
767 out << "signed" << specifier_;
768 }
769
770 void CYTypeUnsigned::Output(CYOutput &out) const {
771 out << "unsigned" << specifier_;
772 }
773
774 void CYTypeVariable::Output(CYOutput &out) const {
775 out << *name_;
776 }
777
778 void CYTypeVoid::Output(CYOutput &out) const {
779 out << "void";
780 }
781
782 void CYVar::Output(CYOutput &out, CYFlags flags) const {
783 out << "var";
784 declarations_->Output(out, flags);
785 out << ';';
786 }
787
788 void CYVariable::Output(CYOutput &out, CYFlags flags) const {
789 out << *name_;
790 }
791
792 void CYWhile::Output(CYOutput &out, CYFlags flags) const {
793 out << "while" << '(' << *test_ << ')';
794 code_->Single(out, CYRight(flags));
795 }
796
797 void CYWith::Output(CYOutput &out, CYFlags flags) const {
798 out << "with" << '(' << *scope_ << ')';
799 code_->Single(out, CYRight(flags));
800 }
801
802 void CYWord::ClassName(CYOutput &out, bool object) const {
803 if (object)
804 out << "objc_getClass(";
805 out << '"' << Word() << '"';
806 if (object)
807 out << ')';
808 }
809
810 void CYWord::Output(CYOutput &out) const {
811 out << Word();
812 if (out.options_.verbose_)
813 out.out_ << '@' << this;
814 }
815
816 void CYWord::PropertyName(CYOutput &out) const {
817 Output(out);
818 }
819
820 const char *CYWord::Word() const {
821 return word_;
822 }