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