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