]> git.saurik.com Git - cycript.git/blob - Output.cpp
Allow multi-line editing and drop libedit support.
[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::ForIn(CYOutput &out, CYFlags flags) const {
272 out << "var" << ' ';
273 Output(out, CYRight(flags));
274 }
275
276 void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
277 out << *identifier_;
278 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
279 if (initialiser_ != NULL) {
280 out << ' ' << '=' << ' ';
281 initialiser_->Output(out, CYAssign::Precedence_, CYRight(flags));
282 }
283 }
284
285 void CYForDeclarations::Output(CYOutput &out, CYFlags flags) const {
286 out << "var" << ' ';
287 declarations_->Output(out, CYRight(flags));
288 }
289
290 void CYDeclarations::Output(CYOutput &out) const {
291 Output(out, CYNoFlags);
292 }
293
294 void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
295 const CYDeclarations *declaration(this);
296 bool first(true);
297
298 for (;;) {
299 CYDeclarations *next(declaration->next_);
300
301 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
302 first = false;
303 declaration->declaration_->Output(out, jacks);
304
305 if (next == NULL)
306 break;
307
308 out << ',' << ' ';
309 declaration = next;
310 }
311 }
312
313 void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
314 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
315 if (const char *word = property_->Word())
316 out << '.' << word;
317 else
318 out << '[' << *property_ << ']';
319 }
320
321 void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
322 out << "do";
323
324 unsigned line(out.position_.line);
325 unsigned indent(out.indent_);
326 code_->Single(out, CYCenter(flags), CYCompactLong);
327
328 if (out.position_.line != line && out.recent_ == indent)
329 out << ' ';
330 else
331 out << '\n' << '\t';
332
333 out << "while" << ' ' << '(' << *test_ << ')';
334 }
335
336 void CYElementSpread::Output(CYOutput &out) const {
337 out << "..." << value_;
338 }
339
340 void CYElementValue::Output(CYOutput &out) const {
341 if (value_ != NULL)
342 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
343 if (next_ != NULL || value_ == NULL) {
344 out << ',';
345 if (next_ != NULL && !next_->Elision())
346 out << ' ';
347 }
348 if (next_ != NULL)
349 next_->Output(out);
350 }
351
352 void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
353 out.Terminate();
354 }
355
356 void CYExpress::Output(CYOutput &out, CYFlags flags) const {
357 expression_->Output(out, flags | CYNoBFC);
358 out << ';';
359 }
360
361 void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
362 Output(out, flags | CYNoRightHand);
363 }
364
365 void CYExpression::Output(CYOutput &out) const {
366 Output(out, CYNoFlags);
367 }
368
369 void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const {
370 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
371 out << '(' << *this << ')';
372 else
373 Output(out, flags);
374 }
375
376 void CYExternal::Output(CYOutput &out, CYFlags flags) const {
377 out << "extern" << abi_ << typed_ << ';';
378 }
379
380 void CYFatArrow::Output(CYOutput &out, CYFlags flags) const {
381 out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << '{' << code_ << '}';
382 }
383
384 void CYFinally::Output(CYOutput &out) const {
385 out << ' ' << "finally" << ' ';
386 out << '{' << '\n';
387 ++out.indent_;
388 out << code_;
389 --out.indent_;
390 out << '\t' << '}';
391 }
392
393 void CYFor::Output(CYOutput &out, CYFlags flags) const {
394 out << "for" << ' ' << '(';
395 if (initialiser_ != NULL)
396 initialiser_->Output(out, CYNoIn);
397 out.Terminate();
398 if (test_ != NULL)
399 out << ' ';
400 out << test_;
401 out.Terminate();
402 if (increment_ != NULL)
403 out << ' ';
404 out << increment_;
405 out << ')';
406 code_->Single(out, CYRight(flags), CYCompactShort);
407 }
408
409 void CYForOf::Output(CYOutput &out, CYFlags flags) const {
410 out << "for" << ' ' << "each" << ' ' << '(';
411 initialiser_->ForIn(out, CYNoIn);
412 out << ' ' << "in" << ' ' << *set_ << ')';
413 code_->Single(out, CYRight(flags), CYCompactShort);
414 }
415
416 void CYForOfComprehension::Output(CYOutput &out) const {
417 out << "for" << ' ' << "each" << ' ' << '(';
418 declaration_->Output(out, CYNoIn);
419 out << ' ' << "in" << ' ' << *set_ << ')' << next_;
420 }
421
422 void CYForIn::Output(CYOutput &out, CYFlags flags) const {
423 out << "for" << ' ' << '(';
424 if (initialiser_ != NULL)
425 initialiser_->ForIn(out, CYNoIn);
426 out << ' ' << "in" << ' ' << *set_ << ')';
427 code_->Single(out, CYRight(flags), CYCompactShort);
428 }
429
430 void CYForInComprehension::Output(CYOutput &out) const {
431 out << "for" << ' ' << '(';
432 declaration_->Output(out, CYNoIn);
433 out << ' ' << "in" << ' ' << *set_ << ')';
434 }
435
436 void CYFunction::Output(CYOutput &out) const {
437 out << '(' << parameters_ << ')' << ' ';
438 out << '{' << '\n';
439 ++out.indent_;
440 out << code_;
441 --out.indent_;
442 out << '\t' << '}';
443 }
444
445 void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
446 // XXX: one could imagine using + here to save a byte
447 bool protect((flags & CYNoFunction) != 0);
448 if (protect)
449 out << '(';
450 out << "function";
451 if (name_ != NULL)
452 out << ' ' << *name_;
453 CYFunction::Output(out);
454 if (protect)
455 out << ')';
456 }
457
458 void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
459 out << "function" << ' ' << *name_;
460 CYFunction::Output(out);
461 }
462
463 void CYFunctionParameter::Output(CYOutput &out) const {
464 initialiser_->Output(out, CYNoFlags);
465 if (next_ != NULL)
466 out << ',' << ' ' << *next_;
467 }
468
469 const char *CYIdentifier::Word() const {
470 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
471 }
472
473 void CYIf::Output(CYOutput &out, CYFlags flags) const {
474 bool protect(false);
475 if (false_ == NULL && (flags & CYNoDangle) != 0) {
476 protect = true;
477 out << '{';
478 }
479
480 out << "if" << ' ' << '(' << *test_ << ')';
481
482 CYFlags right(protect ? CYNoFlags : CYRight(flags));
483
484 CYFlags jacks(CYNoDangle);
485 if (false_ == NULL)
486 jacks |= right;
487 else
488 jacks |= protect ? CYNoFlags : CYCenter(flags);
489
490 unsigned line(out.position_.line);
491 unsigned indent(out.indent_);
492 true_->Single(out, jacks, CYCompactShort);
493
494 if (false_ != NULL) {
495 if (out.position_.line != line && out.recent_ == indent)
496 out << ' ';
497 else
498 out << '\n' << '\t';
499
500 out << "else";
501 false_->Single(out, right, CYCompactLong);
502 }
503
504 if (protect)
505 out << '}';
506 }
507
508 void CYIfComprehension::Output(CYOutput &out) const {
509 out << "if" << ' ' << '(' << *test_ << ')' << next_;
510 }
511
512 void CYImport::Output(CYOutput &out, CYFlags flags) const {
513 out << "@import";
514 }
515
516 void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
517 object_->Output(out, Precedence(), CYLeft(flags));
518 if (const char *word = property_->Word())
519 out << "->" << word;
520 else
521 out << "->" << '[' << *property_ << ']';
522 }
523
524 void CYInfix::Output(CYOutput &out, CYFlags flags) const {
525 const char *name(Operator());
526 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
527 if (protect)
528 out << '(';
529 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
530 lhs_->Output(out, Precedence(), left);
531 out << ' ' << name << ' ';
532 CYFlags right(protect ? CYNoFlags : CYRight(flags));
533 rhs_->Output(out, Precedence() - 1, right);
534 if (protect)
535 out << ')';
536 }
537
538 void CYLabel::Output(CYOutput &out, CYFlags flags) const {
539 out << *name_ << ':';
540 statement_->Single(out, CYRight(flags), CYCompactShort);
541 }
542
543 void CYParenthetical::Output(CYOutput &out, CYFlags flags) const {
544 out << '(';
545 expression_->Output(out, CYCompound::Precedence_, CYNoFlags);
546 out << ')';
547 }
548
549 void CYStatement::Output(CYOutput &out) const {
550 Multiple(out);
551 }
552
553 void CYTemplate::Output(CYOutput &out, CYFlags flags) const {
554 _assert(false);
555 }
556
557 void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
558 next_->Output(out, Precedence(), identifier);
559 out << '[';
560 out << size_;
561 out << ']';
562 }
563
564 void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
565 out << '(' << '^';
566 next_->Output(out, Precedence(), identifier);
567 out << ')' << '(' << parameters_ << ')';
568 }
569
570 void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
571 out << "const" << ' ';
572 next_->Output(out, Precedence(), identifier);
573 }
574
575 void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
576 next_->Output(out, Precedence(), identifier);
577 out << '(' << parameters_ << ')';
578 }
579
580 void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
581 out << '*';
582 next_->Output(out, Precedence(), identifier);
583 }
584
585 void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
586 out << "volatile";
587 next_->Output(out, Precedence(), identifier);
588 }
589
590 void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
591 if (this == NULL) {
592 out << identifier;
593 return;
594 }
595
596 bool protect(precedence > Precedence());
597
598 if (protect)
599 out << '(';
600 Output(out, identifier);
601 if (protect)
602 out << ')';
603 }
604
605 void CYTypedIdentifier::Output(CYOutput &out) const {
606 specifier_->Output(out);
607 modifier_->Output(out, 0, identifier_);
608 }
609
610 void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
611 out << "@encode(" << typed_ << ")";
612 }
613
614 void CYTypedParameter::Output(CYOutput &out) const {
615 out << typed_;
616 if (next_ != NULL)
617 out << ',' << ' ' << next_;
618 }
619
620 void CYLambda::Output(CYOutput &out, CYFlags flags) const {
621 // XXX: this is seriously wrong
622 out << "[](";
623 out << ")->";
624 out << "{";
625 out << "}";
626 }
627
628 void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
629 out << "typedef" << ' ' << *typed_;
630 }
631
632 void CYLet::Output(CYOutput &out, CYFlags flags) const {
633 out << "let" << ' ';
634 declarations_->Output(out, flags); // XXX: flags
635 out << ';';
636 }
637
638 void CYModule::Output(CYOutput &out) const {
639 out << part_;
640 if (next_ != NULL)
641 out << '.' << next_;
642 }
643
644 namespace cy {
645 namespace Syntax {
646
647 void New::Output(CYOutput &out, CYFlags flags) const {
648 out << "new" << ' ';
649 CYFlags jacks(CYNoCall | CYCenter(flags));
650 constructor_->Output(out, Precedence(), jacks);
651 if (arguments_ != NULL)
652 out << '(' << *arguments_ << ')';
653 }
654
655 } }
656
657 void CYNull::Output(CYOutput &out, CYFlags flags) const {
658 out << "null";
659 }
660
661 void CYNumber::Output(CYOutput &out, CYFlags flags) const {
662 std::ostringstream str;
663 CYNumerify(str, Value());
664 std::string value(str.str());
665 out << value.c_str();
666 // XXX: this should probably also handle hex conversions and exponents
667 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
668 out << '.';
669 }
670
671 void CYNumber::PropertyName(CYOutput &out) const {
672 Output(out, CYNoFlags);
673 }
674
675 void CYObject::Output(CYOutput &out, CYFlags flags) const {
676 bool protect((flags & CYNoBrace) != 0);
677 if (protect)
678 out << '(';
679 out << '{' << '\n';
680 ++out.indent_;
681 out << properties_;
682 --out.indent_;
683 out << '\t' << '}';
684 if (protect)
685 out << ')';
686 }
687
688 void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
689 lhs_->Output(out, Precedence(), CYLeft(flags));
690 out << Operator();
691 }
692
693 void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
694 const char *name(Operator());
695 out << name;
696 if (Alphabetic())
697 out << ' ';
698 rhs_->Output(out, Precedence(), CYRight(flags));
699 }
700
701 void CYScript::Output(CYOutput &out) const {
702 out << code_;
703 }
704
705 void CYProperty::Output(CYOutput &out) const {
706 if (next_ != NULL || out.pretty_)
707 out << ',';
708 out << '\n' << next_;
709 }
710
711 void CYPropertyGetter::Output(CYOutput &out) const {
712 out << "get" << ' ';
713 name_->PropertyName(out);
714 CYFunction::Output(out);
715 CYProperty::Output(out);
716 }
717
718 void CYPropertyMethod::Output(CYOutput &out) const {
719 name_->PropertyName(out);
720 CYFunction::Output(out);
721 CYProperty::Output(out);
722 }
723
724 void CYPropertySetter::Output(CYOutput &out) const {
725 out << "set" << ' ';
726 name_->PropertyName(out);
727 CYFunction::Output(out);
728 CYProperty::Output(out);
729 }
730
731 void CYPropertyValue::Output(CYOutput &out) const {
732 out << '\t';
733 name_->PropertyName(out);
734 out << ':' << ' ';
735 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
736 CYProperty::Output(out);
737 }
738
739 void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
740 out << Value();
741 }
742
743 void CYReturn::Output(CYOutput &out, CYFlags flags) const {
744 out << "return";
745 if (value_ != NULL)
746 out << ' ' << *value_;
747 out << ';';
748 }
749
750 void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
751 call_->Output(out, CYLeft(flags));
752 out << ' ';
753 proc_->Output(out, CYRight(flags));
754 }
755
756 void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
757 out << '{' << ' ' << '|' << parameters_ << '|' << '\n';
758 ++out.indent_;
759 out << code_;
760 --out.indent_;
761 out << '\t' << '}';
762 }
763
764 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
765 bool first(true);
766 CYForEach (next, this) {
767 bool last(next->next_ == NULL);
768 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
769 first = false;
770 out << '\t';
771 next->Output(out, jacks);
772 out << '\n';
773 }
774 }
775
776 void CYStatement::Single(CYOutput &out, CYFlags flags, CYCompactType request) const {
777 if (this == NULL)
778 return out.Terminate();
779
780 _assert(next_ == NULL);
781
782 CYCompactType compact(Compact());
783
784 if (compact >= request)
785 out << ' ';
786 else {
787 out << '\n';
788 ++out.indent_;
789 out << '\t';
790 }
791
792 Output(out, flags);
793
794 if (compact < request)
795 --out.indent_;
796 }
797
798 void CYString::Output(CYOutput &out, CYFlags flags) const {
799 std::ostringstream str;
800 CYStringify(str, value_, size_);
801 out << str.str().c_str();
802 }
803
804 void CYString::PropertyName(CYOutput &out) const {
805 if (const char *word = Word())
806 out << word;
807 else
808 out << *this;
809 }
810
811 static const char *Reserved_[] = {
812 "false", "null", "true",
813
814 "break", "case", "catch", "continue", "default",
815 "delete", "do", "else", "finally", "for", "function",
816 "if", "in", "instanceof", "new", "return", "switch",
817 "this", "throw", "try", "typeof", "var", "void",
818 "while", "with",
819
820 "debugger", "const",
821
822 "class", "enum", "export", "extends", "import", "super",
823
824 "abstract", "boolean", "byte", "char", "double", "final",
825 "float", "goto", "int", "long", "native", "short",
826 "synchronized", "throws", "transient", "volatile",
827
828 "let", "yield",
829
830 NULL
831 };
832
833 const char *CYString::Word() const {
834 if (size_ == 0 || !WordStartRange_[value_[0]])
835 return NULL;
836 for (size_t i(1); i != size_; ++i)
837 if (!WordEndRange_[value_[i]])
838 return NULL;
839 const char *value(Value());
840 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
841 if (strcmp(*reserved, value) == 0)
842 return NULL;
843 return value;
844 }
845
846 void CYSuperAccess::Output(CYOutput &out, CYFlags flags) const {
847 out << "super";
848 if (const char *word = property_->Word())
849 out << '.' << word;
850 else
851 out << '[' << *property_ << ']';
852 }
853
854 void CYSuperCall::Output(CYOutput &out, CYFlags flags) const {
855 out << "super" << '(' << arguments_ << ')';
856 }
857
858 void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
859 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{' << '\n';
860 ++out.indent_;
861 out << clauses_;
862 --out.indent_;
863 out << '\t' << '}';
864 }
865
866 void CYThis::Output(CYOutput &out, CYFlags flags) const {
867 out << "this";
868 }
869
870 namespace cy {
871 namespace Syntax {
872
873 void Throw::Output(CYOutput &out, CYFlags flags) const {
874 out << "throw";
875 if (value_ != NULL)
876 out << ' ' << *value_;
877 out << ';';
878 }
879
880 void Try::Output(CYOutput &out, CYFlags flags) const {
881 out << "try" << ' ';
882 out << '{' << '\n';
883 ++out.indent_;
884 out << code_;
885 --out.indent_;
886 out << '\t' << '}';
887 out << catch_ << finally_;
888 }
889
890 } }
891
892 void CYTypeError::Output(CYOutput &out) const {
893 out << "@error";
894 }
895
896 void CYTypeLong::Output(CYOutput &out) const {
897 out << "long" << specifier_;
898 }
899
900 void CYTypeShort::Output(CYOutput &out) const {
901 out << "short" << specifier_;
902 }
903
904 void CYTypeSigned::Output(CYOutput &out) const {
905 out << "signed" << specifier_;
906 }
907
908 void CYTypeUnsigned::Output(CYOutput &out) const {
909 out << "unsigned" << specifier_;
910 }
911
912 void CYTypeVariable::Output(CYOutput &out) const {
913 out << *name_;
914 }
915
916 void CYTypeVoid::Output(CYOutput &out) const {
917 out << "void";
918 }
919
920 void CYVar::Output(CYOutput &out, CYFlags flags) const {
921 out << "var" << ' ';
922 declarations_->Output(out, flags); // XXX: flags
923 out << ';';
924 }
925
926 void CYVariable::Output(CYOutput &out, CYFlags flags) const {
927 out << *name_;
928 }
929
930 void CYWhile::Output(CYOutput &out, CYFlags flags) const {
931 out << "while" << ' ' << '(' << *test_ << ')';
932 code_->Single(out, CYRight(flags), CYCompactShort);
933 }
934
935 void CYWith::Output(CYOutput &out, CYFlags flags) const {
936 out << "with" << ' ' << '(' << *scope_ << ')';
937 code_->Single(out, CYRight(flags), CYCompactShort);
938 }
939
940 void CYWord::Output(CYOutput &out) const {
941 out << Word();
942 if (out.options_.verbose_) {
943 out('@');
944 char number[32];
945 sprintf(number, "%p", this);
946 out(number);
947 }
948 }
949
950 void CYWord::PropertyName(CYOutput &out) const {
951 Output(out);
952 }
953
954 const char *CYWord::Word() const {
955 return word_;
956 }