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