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