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