]> git.saurik.com Git - cycript.git/blob - Output.cpp
d45a7397489e928d45471a4501acea9f23b3c809
[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 out << '{' << ' ' << '|' << parameters_ << '|' << '\n';
688 ++out.indent_;
689 out << code_;
690 --out.indent_;
691 out << '\t' << '}';
692 }
693
694 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
695 bool first(true);
696 CYForEach (next, this) {
697 bool last(next->next_ == NULL);
698 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
699 first = false;
700 out << '\t';
701 next->Output(out, jacks);
702 out << '\n';
703 }
704 }
705
706 void CYStatement::Single(CYOutput &out, CYFlags flags, CYCompactType request) const {
707 if (this == NULL)
708 return out.Terminate();
709
710 _assert(next_ == NULL);
711
712 CYCompactType compact(Compact());
713
714 if (compact >= request)
715 out << ' ';
716 else {
717 out << '\n';
718 ++out.indent_;
719 out << '\t';
720 }
721
722 Output(out, flags);
723
724 if (compact < request)
725 --out.indent_;
726 }
727
728 void CYString::Output(CYOutput &out, CYFlags flags) const {
729 std::ostringstream str;
730 CYStringify(str, value_, size_);
731 out << str.str().c_str();
732 }
733
734 void CYString::PropertyName(CYOutput &out) const {
735 if (const char *word = Word())
736 out << word;
737 else
738 out << *this;
739 }
740
741 static const char *Reserved_[] = {
742 "false", "null", "true",
743
744 "break", "case", "catch", "continue", "default",
745 "delete", "do", "else", "finally", "for", "function",
746 "if", "in", "instanceof", "new", "return", "switch",
747 "this", "throw", "try", "typeof", "var", "void",
748 "while", "with",
749
750 "debugger", "const",
751
752 "class", "enum", "export", "extends", "import", "super",
753
754 "abstract", "boolean", "byte", "char", "double", "final",
755 "float", "goto", "int", "long", "native", "short",
756 "synchronized", "throws", "transient", "volatile",
757
758 "let", "yield",
759
760 NULL
761 };
762
763 const char *CYString::Word() const {
764 if (size_ == 0 || !WordStartRange_[value_[0]])
765 return NULL;
766 for (size_t i(1); i != size_; ++i)
767 if (!WordEndRange_[value_[i]])
768 return NULL;
769 const char *value(Value());
770 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
771 if (strcmp(*reserved, value) == 0)
772 return NULL;
773 return value;
774 }
775
776 void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
777 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{' << '\n';
778 ++out.indent_;
779 out << clauses_;
780 --out.indent_;
781 out << '\t' << '}';
782 }
783
784 void CYThis::Output(CYOutput &out, CYFlags flags) const {
785 CYWord::Output(out);
786 }
787
788 namespace cy {
789 namespace Syntax {
790
791 void Throw::Output(CYOutput &out, CYFlags flags) const {
792 out << "throw";
793 if (value_ != NULL)
794 out << ' ' << *value_;
795 out << ';';
796 }
797
798 void Try::Output(CYOutput &out, CYFlags flags) const {
799 out << "try" << ' ';
800 out << '{' << '\n';
801 ++out.indent_;
802 out << code_;
803 --out.indent_;
804 out << '\t' << '}';
805 out << catch_ << finally_;
806 }
807
808 } }
809
810 void CYTypeError::Output(CYOutput &out) const {
811 out << "@error";
812 }
813
814 void CYTypeLong::Output(CYOutput &out) const {
815 out << "long" << specifier_;
816 }
817
818 void CYTypeShort::Output(CYOutput &out) const {
819 out << "short" << specifier_;
820 }
821
822 void CYTypeSigned::Output(CYOutput &out) const {
823 out << "signed" << specifier_;
824 }
825
826 void CYTypeUnsigned::Output(CYOutput &out) const {
827 out << "unsigned" << specifier_;
828 }
829
830 void CYTypeVariable::Output(CYOutput &out) const {
831 out << *name_;
832 }
833
834 void CYTypeVoid::Output(CYOutput &out) const {
835 out << "void";
836 }
837
838 void CYVar::Output(CYOutput &out, CYFlags flags) const {
839 out << "var" << ' ';
840 declarations_->Output(out, flags);
841 out << ';';
842 }
843
844 void CYVariable::Output(CYOutput &out, CYFlags flags) const {
845 out << *name_;
846 }
847
848 void CYWhile::Output(CYOutput &out, CYFlags flags) const {
849 out << "while" << ' ' << '(' << *test_ << ')';
850 code_->Single(out, CYRight(flags), CYCompactShort);
851 }
852
853 void CYWith::Output(CYOutput &out, CYFlags flags) const {
854 out << "with" << ' ' << '(' << *scope_ << ')';
855 code_->Single(out, CYRight(flags), CYCompactShort);
856 }
857
858 void CYWord::ClassName(CYOutput &out, bool object) const {
859 if (object)
860 out << "objc_getClass(";
861 out << '"' << Word() << '"';
862 if (object)
863 out << ')';
864 }
865
866 void CYWord::Output(CYOutput &out) const {
867 out << Word();
868 if (out.options_.verbose_) {
869 out('@');
870 char number[32];
871 sprintf(number, "%p", this);
872 out(number);
873 }
874 }
875
876 void CYWord::PropertyName(CYOutput &out) const {
877 Output(out);
878 }
879
880 const char *CYWord::Word() const {
881 return word_;
882 }