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