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