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