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