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