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