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